[TIL] class_2

chaerin·2021년 2월 12일
1

TIL

목록 보기
4/4
post-thumbnail

클래스 속성과 인스턴스 속성

클래스 속성

클래스 속성은 다음과 같이 클래스에 바로 속성을 만든다.

class 클래스이름:
    속성 =

사람 클래스에 클래스 속성으로 가방 속성을 넣고 사용해보자.

아래와 같이 Person 클래스에 bag 속성을 넣고, put_bag 메서드를 만든다. 그리고 인스턴스 두 개를 만든 뒤 각각 put_bag 메서드를 사용한다.

class Person:
    bag = []
 
    def put_bag(self, stuff):
        self.bag.append(stuff)
 
james = Person()
james.put_bag('책')
 
maria = Person()
maria.put_bag('열쇠')
 
print(james.bag)
print(maria.bag)

위 코드를 실행해서 결과를 확인해보면 아래와 같이 넣었던 물건이 합쳐서 나온다.

['책', '열쇠']
['책', '열쇠']

✅ 이로써 클래스 속성은 클래스에 속해 있으며 모든 인스턴스에서 공유한다는 것을 알 수 있다.

put_bag 메서드에서 클래스 속성 bag에 접근할 때 self를 사용했다. self는 현재 인스턴스를 뜻하므로 클래스 속성에 접근할 때는 다음과 같이 클래스 이름으로 접근하면 좀 더 코드가 명확해 진다.

  • 클래스.속성
class Person:
    bag = []
 
    def put_bag(self, stuff):
        Person.bag.append(stuff)    # 클래스 이름으로 클래스 속성에 접근

속성, 메서드 이름을 찾는 순서
파이썬에서는 속성, 메서드 이름을 찾을 때 인스턴스, 클래스 순으로 찾는다. 그래서 인스턴스 속성이 없으면 클래스 속성을 찾게 된다.

james.bag, maria.bag 도 겉보기에는 인스턴스 속성을 사용하는 것 같지만 실제로는 클래스 속성이다.

인스턴스 속성

속성을 공유하고 싶지 않다면 인스턴스 속성으로 만들면 된다.

class Person:
    def __init__(self):
        self.bag = []
 
    def put_bag(self, stuff):
        self.bag.append(stuff)
 
james = Person()
james.put_bag('책')
 
maria = Person()
maria.put_bag('열쇠')
 
print(james.bag)
print(maria.bag)
실행 결과
['책']
['열쇠']

실행 결과를 확인해 보면 각자 넣은 물건만 출력된 것을 확인할 수 있다.

✅ 즉, 인스턴스 속성은 인스턴스별로 독립되어 있으며 서로 영향을 주지 않는다.

🔆 클래스 속성과 인스턴스 속성의 차이점

  • 클래스 속성
    • 모든 인스턴스가 공유
    • 인스턴스 전체가 사용해야 하는 값을 저장할 때 사용
  • 인스턴스 속성
    • 인스턴스별로 독립되어 있음
    • 각 인스턴스가 값을 따로 저장해야 할 때 사용

정적 메서드와 클래스 메서드

정적 메서드와 클래스 메서드는 인스턴스를 통하지 않고 클래스에서 바로 호출할 수 있다.

정적 메서드

정적 메서드는 다음과 같이 메서드 위에 @staticmethod를 붙인다. 이 때 정적 메서드는 매개변수에 self를 지정하지 않는다.

class 클래스이름:
    @staticmethod
    def 메서드(매개변수1, 매개변수2):
        코드

@staticmethod처럼 앞에 @이 붙은 것을 데코레이터라고 하며 메서드(함수)에 추가 기능을 구현할 때 사용한다.

아래와 같이 @staticmethod 를 붙여서 덧셈과 곱셈을 하는 메서드를 만들면 클래스에서 바로 메서드를 호출할 수 있다.

class Calc:
    @staticmethod
    def add(a, b):
        print(a + b)
 
    @staticmethod
    def mul(a, b):
        print(a * b)
 
Calc.add(10, 20)    # 클래스에서 바로 메서드 호출
Calc.mul(10, 20)    # 클래스에서 바로 메서드 호출

실행결과
30
200

정적 메서드는 self를 받지 않으므로 인스턴스 속성에 접근할 수 없다. 그래서 보통 정적 메서드는 인스턴스 속성, 인스턴스 메서드가 필요 없을 때 사용한다.

✔️무엇을 정적 메서드로 만들어야 할까?
정적 메서드는 메서드의 실행이 외부 상태에 영향을 끼치지 않는 순수 함수(pure function)를 만들 때 사용한다. 순수 함수는 부수 효과가 없고 입력 값이 같으면 언제나 같은 출력 값을 반환한다.

즉, 정적 메서드는 인스턴스의 상태를 변화시키지 않는 메서드를 만들 때 사용한다.

클래스 메서드

클래스 메서드는 다음과 같이 메서드 위에 @classmethod를 붙인다. 이 때 클래스 메서드는 첫 번째 매개변수에 cls를 지정해야 한다.

class 클래스이름:
    @classmethod
    def 메서드(cls, 매개변수1, 매개변수2):
        코드

사람 클래스 Person을 만들고 인스턴스가 몇 개 만들어 졌는지 출력하는 메서드를 만들어보자.

class Person:
    count = 0    # 클래스 속성
 
    def __init__(self):
        Person.count += 1    # 인스턴스가 만들어질 때
                             # 클래스 속성 count에 1을 더함
 
    @classmethod
    def print_count(cls):
        print('{0}명 생성되었습니다.'.format(cls.count))    # cls로 클래스 속성에 접근
 
james = Person()
maria = Person()
 
Person.print_count() 

실행 결과
2명 생성되었습니다.

클래스 메서드의 첫 번째 매개변수 cls 에는 현재 클래스가 들어온다. 따라서 cls.count 처럼 cls 로 클래스 속성 count에 접근할 수 있다.

클래스 메서드는 정적 메서드처럼 인스턴스 없이 호출할 수 있다는 점은 같다.
하지만 클래스 메서드는 메서드 안에서 클래스 속성, 클래스 메서드에 접근해야 할 때 사용한다.

특히 cls를 사용하면 메서드 안에서 현재 클래스의 인스턴스를 만들 수도 있다. 즉, 위의 코드에서는 cls는 클래스를 뜻하므로 cls() == Person()고 할 수 있다.



참고사이트 : https://dojang.io/mod/page/view.php?id=2380

0개의 댓글