파이썬 클래스 함수 차이 - paisseon keullaeseu hamsu chai

내 맘대로 생각하는 파이썬


'모든 것이 객체입니다'

파이썬에서는 어떤 객체도 동적으로 변수에 할당할 수 있습니다. 그렇다면 '파이썬에서 객체란 무엇일까요?' 이 질문에 대한 대답은 '모든 것이 객체'라는 겁니다.

파이썬에서 모든 데이터 값이 객체입니다. 예를 들어 '놀라지 마세요!' 같은 문자열 객체나 42같은 숫자 객체가 있습니다. 다른 프로그래밍 언어와 마찬가지로 파이썬 객체는 속성이나 값을 나타내는 상태( state )와 메서드에 해당하는 행동 ( behavoir )을 가질 수 있습니다.

요약하면 파이썬에서 모든 것은 클래스로부터 상속받은 객체처럼 동작합니다. 이러한 점에서 파이썬은 객체 지향이라기보다는 객체 기반 ( object-based ) 이라고 표현하는 것이 더 적절합니다. 즉 파이썬에서 객체지향은 단지 선택사항일 뿐입니다.
 - '헤드 퍼스트 파이썬 p89'

모든 것이 최초의 빌트인 클래스로부터 상속받은 객체이다.

그렇다면 클래스를 쓰지 않고 함수만으로 코드를 작성한다는 것은 도대체 무슨 뜻일까?

즉 기존의 다른 언어들의 객체지향( 클래스 지향? ) 적인 특성이 아닌 객체 기반 ( object-based ) 적으로 코드를 작성한다는 것이다.

이 말은 매우 햇갈리지만

클래스를 배제한 것이 아닌, '최초의 클래스' 의 판 안에서만 놀아난다고 보면 이해할 수 있을 것 같다.

더이상의 새로운 클래스를 형성하지 않고 이미 만들어진 클래스안에서 새로운 함수 ( 새로운 행동 ) 만으로 코드를 작성한다.

즉 이미 공유하고있던관념이나 개념을 그대로 상속하여 사용한다는 것이다.

어떤 국가가 있으면 그 국가 안에서 새로운 정의와 철학을 가진 새로운 국가를 선포하는 것이 아니라,

이미 있던 국가의 테두리 안에서 다른 행동만을 한다는 뜻이다. 대전제와 큰 범위는 바뀌지 않는다.

객체를 지향한다는 것은, 클래스를 만드는 것을 지향한다는 것은

계속해서 새로운 문법, 새로운 사람, 새로운 창업 등 새롭게 규정된 것을 만들어내서 그것을 공유하는 테두리, 틀을 만드는 것을 계속해서 지향한다는 소리다.

'사람은 고쳐쓰는게 아니다' 라고 생각하여 새롭게 태어나는 아이들(신상 객체)을 교육시키는 것에 집중하는 것은 객체지향적인 태도이다.

객체를 기반 한다는 것은 이미 있는 기반 위에서, 어떤 규칙 안에서 새로운 행동을 하겠다는 소리다.

위 예시와 반대로 기존에 있던 사람들도 변할 수 있다고 믿고 평생교육을 실천하는 태도이다.

객체지향이라고해서 본래에 있었던 최초의 클래스를 무시할 수 있다는 것도 아니고

객체 기반이라고해서 객체를 쓰지 않는다는 소리도 아니다.

필요할 때 필요한 것을 사용하는 것이 올바른 태도이다.


def imking():
	global z --->> z가 함수 내에 없으면 전역 클래스에서 z를 찾아서 가져오도록 함.
	print(z) ->>>>>> 10 
	z = 2
    print(z)   ->>>>>> 2
    return z
    
z = 10
imking()

print(z) -----> 호출했는데도 10

함수라는 것은 언제나 전역 클래스에 '종속' 되어 있다.

함수라는 새로운 행동을 만들어 z 는 2다!! 라고 외쳐도, 그것은 외치는 순간만 2이고

그 바깥에서는 이미 전역 클래스에 담겨져있는 z 가 10이다 라는 사실, 상태(state)는 바뀌지 않는다.

함수는 문맥( context )이 있을 수 없는 단일적으로 휘발되는 행동으로 규정된다.

휘발되어야만 하는 것들도 있기에 그것을 활용하기 위해서 사용한다.

class Country:
    def __init__(self):
        self.z = 2


z = 10

c = Country()
print(z) ====> 10
print(c.z)    =====> 2

클래스는 새로운 나라를 선포하고 성벽을 올린다.

모두가 공유하는 어떤 것을 분명하게 정의하고 그 새로운 틀안에서 모든것이 생겨난다. 

종속되지 않는 = 기억에 계속해서 남는 자기만의 상태와 행동을 지속적으로 가질 수 있다.

그런것들이 프로그래밍할 때 필요하니까 만들어 둔 것이다.

함수와 클래스 모두 전역적인 세계 (World)에서 약간의 공간을 빌려 무언가를 하는 것은 완전히 동일하다.

하지만 동네에서 자기 집 울타리를 짓는 것과

나라를 선포하고 울타리를 치는 것은 차원이 틀린 이야기다.

새로운 종류, 기존과는 전혀다른 차이를 보이는 특성들을 지속적으로 만들어내겠다는 선포이다.

그 말은 곧 기존 세계의 문법을 지키지 않고 그 공간을 계속해서 점유하고 바뀌지 않는 고유함으로 만들어나가겠다는 뜻이다.

파이썬 클래스에서 꼭 self를 붙여야만 고유한 상태 변수를 유지할 수 있는 것이 같은 맥락에서의 이유이다.

클래스로 객체가 생성될때마다 고정된 위치를 기억해야하기 때문이다.

컨텍스트 관리자는 무조건 클래스로 만들어야 하듯이 클래스는 문맥을 기억하고 이해할 수 있도록 만들어 준다.

새로운 클래스 안에도 함수가 있을 수 있고, 그 새로운 클래스안에서 또다른 클래스가 파생되면서 계속해서 복잡해지는 모습은 마치 인류의 진화과정과 같은 모습이다.

파이썬에서의 모든 것이 객체다 라는 말처럼 리처드 파인만이 세상의 모든 것은 원자로 구성되어있다. 라고 말한 것이 기억난다. 최초의 상태에서 계속해서 압축되고 추상화되고 새롭게 정의되기도 하면서 만들어나갈 수 있는 프로그래밍과 세상은 똑같은 개념이 아닐까 생각이 든다.

그저 기능하느냐 새롭게 자신만의 색깔을 입고 기능하느냐. 클래스가 다른 전혀 다른 색깔을 보여주는 프로선수들을 생각해보자.

회사의 직원으로 기능할 것인가, 아니면 창업해서 새로운 비지니스를 만들고 그 안에서 기능할 것이냐의 차이라고 보면 쉬울 것 같다.

1. 함수: 코드를 기능으로 묶은 단위, (어떤 기능을 코드로 묶은 것)

만약 함수가 없는 세상이 있다고 생각해봅시다.

그러면 우리가 게시판 페이지를 만들 경우 매번 댓글 기능을 하는 코드를 만들어줘야 합니다.

자, 이럴 때를 위해 함수가 만들어졌습니다.

반복이 필요한 경우, 그 기능을 하느 코드를 함수로 묶어두어

필요할 때마다 그 함수를 부르기만 하면 되는거죠.

또 함수없이 코드를 짜게 되면 일렬로 주욱 나열되는데,

그러면 나중에 코드를 확인 하는 것이 어려워집니다.

그래서 댓글기능, 글쓰기 기능 등 기능별로 나누어서 

묶어주면 코드의 흐름을 파악하기 쉬어요.

예를 들어 '아! 댓글 쓰기 기능에서 실수를 했구나' 이렇게 되는거죠.

 2. 함수의 구조

def 함수명(매개변수):
    <수행할 문장1>
    <수행할 문장2>
    return 리턴값

 - 함수는 들어온 입력값(매개변수)을 받아

  어떤 처리(수행할 문장)를 하여 적절한 결과값(리턴값)을 돌려준다.

 - def: (파이썬에서 사용하는)함수를 만들기 위한 예약어. 

 - 함수명: 변수와 같이 사용자가 임의로 정할 수 있음.

 - 매개변수(parameter) : 이 함수의 입구로 전달되는 값을 받는 변수,

   여러 변수를 받을 수 있고 아무것도 받지 않을 수도 있다.

   *매개변수가 들어갈 괄호()를 입구라 하겠습니당.

 - 리턴값단 하나, 리턴값이 존재하지 않을 수도 있음.

=> len, count 같은 내장함수들도

def len()이라는 함수가 파이썬에 저장되어 있고, return으로 길이값을 주게 만들어진 함수!

이처럼 내장함수는 누군가가 만들어놓은 함수고, 

우리가 직접 함수를 만들 수도 있는데요.

def addfunction(a, b): 
    return a + b

이는 함수의 이름은 addfunction이고 입구로 2개의 값을 받으며 리턴값(결과값)은 2개의 입력값을 더한 값이다.

자 그렇다면 실제로 addfunction 함수를 호출해볼까요?

def add(a, b): 
    return a + b
        
c = add(2, 3) #함수 호출
print(c)    

이때 매개변수인수라는 개념이 등장합니다.

매개변수는 함수에 입구로 전달된 값을 받는 변수의미하고

인수는 함수를 호출할 때 전달하는 입력값을 의미합니다.

def add(a, b): #a,b는 매개변수
    return a + b
        
c = add(2, 3) #2,3은 인수
print(c)    

2. 함수에서의 변수

 1) 지역변수

함수 내에서 만들어진, 함수 내에서만 사용 가능한 변수입니다.

함수는 하나의 공간으로 함수 내 변수와 밖에 있는 변수는 구분됩니다.

그래서 함수 밖에서 num이라는 변수가 있고, 함수 내에서 num이라는 변수가 있으면

둘은 다른 아이로 구분되어집니다.

*그렇다면 밖에서도 쓸 수 있고, 안에서도 쓸 수 있는 변수가 없을까?

이를 전역변수라 합니다.

 2) 전역변수

코드 전체의 영역에서 영향력을 갖는 변수를 말합니다.

변수 앞에 global을 붙여주면 됩니다.

global 변수

=> 전역 변수를 무작위로 사용하게 되면, 나중에 에러를 볼 때

어느 곳에서 에러가 났는지 잘 보이지 않아 애초에 함수를 묶는 의미가 사라지니

최대한 사용하지 않는 것을 추천드립니다:).

3. Class

 - 어떤 물건을 만들기 위한 , 공장과 같은 역할을 하며

 자신의 형태와 똑같은 결과물(객체)을 찍어 낼 수 있는 도구, 설계도입니다.

 객체의 설계도라고 불리죠.

* 메모리에 저장된 자료를 객체

* 객체를 저장한 공간을 변수, 변수의 이름을 변수명

* 클래스에 의해 만들어진 객체를 인스턴스(instance)

전혀 이해가 안가시죠?

이를 이해하기 위해서는 우선 왜 클래스가 탄생했는지를 알아야 합니다.

1) 클래스는 왜 필요할까??

예를 들어 게임을 하나 만든다고 가정해봅시다.

기사와 법사라는 캐릭터가 있고, 각각 hp, mp, 하나의 공격에 입힐 수 있는 demage가 있습니다.

 #전사, 법사
knight_name = "기사"
knight_hp = 200
knight_mp = 20
knight_damage = 10

print(knight_name,"체력은",knight_hp,"이고, 마력은", knight_mp)
Wizard_name = "법사"
Wizard_hp = 100
Wizard_mp = 100
Wizard_damage = 15

print("{0} 체력은 {1} 이고, 마력은 {2}".format(Wizard_name,Wizard_hp,Wizard_mp) )

 자 이제 이 두 캐릭터가 공격을 할 수 있다고 할 때,

그 공격 기능을 하는 함수를 만들어 볼까요?

def attack(name, skill, damage):
    print("{0}은 {1}스킬을 시전하여 {2} 데미지를 입힐 수 있습니다.".format(name,skill,damage))
    
attack(knight_name,"찌르기",knight_damage)
attack(Wizard_name,"석화",Wizard_damage)

 자 이때 법사가 한명이 아니라 두명이라면?

Wizard_name2 = "법사"
Wizard_hp2 = 100
Wizard_mp2 = 100
Wizard_damage2 = 15

이런식으로 만들 수 있지만, 

만약 캐릭터가 수백 수천개면 이렇게 계속 복붙을 하며 만들어줘야 할까요?

클래스의 개념을 이용하면 이러한 문제는 쉽게 해결될 수 있습니다.

클래스는 "틀"과 같은 성격을 가지고 있거든요.

즉 저는 클래스라는 것이 같은 문제를 해결하는 변수 및 함수의 반복을 막기 위해 탄생한 아이라고 저만의 정의를 내려봅니다.

이를 클래스화 시켜주면 다음과 같습니다.

class Game:
    def __init__(self, name, hp, mp, damage): #생성자, 자동으로 호출
        self.name = name
        self.hp =hp
        self.mp =mp
        self.damage = damage
        print("{0} 캐릭터가 생성되었습니다.".format(self.name))
        print("체력{0}, 마력{1}, 공격력{2}을 가지고 있습니다.".format(self.hp,self.mp,self.damage))

    def attack(self, skill):
        print("{0}은 {1}스킬을 시전하여 {2} 데미지를 입힐 수 있습니다."\
            .format(self.name,skill,self.damage)) 

    
knight = Game("기사",200,50,15)
Wizard1 = Game("법사",100,100,15)
Wizard2 = Game("법사2",100,80,25)
Wizard2.hp = 300 #객체의 속성에 변화 주기
Wizard2.attack("석화") #객체의 클래스에 변화 주기
#클래스로부터 만들어지는 것을 객체 

클래스 구조

* 속성과 메소드

- 클래스에 속한 데이터를 멤버변수 ex) 이름, hp, mp - 속성

- 클래스에 속하는 기능을 메서드 ex) 찌르기, 석화 - 기능

class 클래스명:
    def __init__(self): #생성자로 호출할 때 초기값을 준다.
        self.속성 = 변수
         #클래스에서 자기 자신을 의미하는 전달값 self
        
    def 함수명(self,매개변수): #self는 class내 모든 메소드에 들어가야 하며, 이 코드 식에서는 cal1,cal2 등이 들어간다.
       수행할 문장

객체명 = 클래스명() 
객체명.속성 = 값을 넣어줄 수 있음
객체명.메소드() #클래스 내에 있는 함수를 메소드라 칭함

'개발 > Python' 카테고리의 다른 글

[파이썬] lambda, sort - 리스트 특정 조건, 다중 조건 정렬  (0) 2020.09.01
리스트, 딕셔너리 함수 - 추가, 삭제, 길이, 정렬  (0) 2020.06.23
파이썬 문자열 내장함수 - 길이, 특정 문자 개수, 나누기  (0) 2020.06.23
파이썬 자료형 - 리스트, 튜플, 딕셔너리 차이  (1) 2020.06.19
파이썬 자료형- 숫자형 자료형, 문자형 자료형  (0) 2020.06.04