IT/파이썬

[코딩도장] day24. 파이썬 클래스 속성과 정적, 클래스 메서드 사용하기

_하늘여우_ 2020. 9. 18. 23:59

출처 : unsplash

■ 들어가기

- 파이썬 코딩 도장 (남재윤/길벗). 을 공부하며 정리하는 블로그


▶ Unit35. 클래스 속성과 정적, 클래스 메서드 사용하기

     - 35.1 클래스 속성과 인스턴스 속성 알아보기

     - 35.2 정적 메서드 사용하기

     - 35.3 클래스 메서드 사용하기

 

>> 35.1 클래스 속성과 인스턴스 속성 알아보기 <<

- 클래스의 속성에는 '클래스 속성'과 '인스턴스 속성'이 존재함.

 

1. 클래스 속성 사용하기

- 클래스에 바로 속성을 만듦

- 사용법

class 클래스이름 :

    속성 = 값

- 예제: 사람 클래스에 클래스 속성으로 '가방 속성'을 넣고 사용

소스 (class_class_attribute.py) 결과
class Person :
    bag = []    # 클래스 속성 생성

    def put_bag(self, stuff) :  # 메서드(클래스 내 함수)의 첫 번째 매개변수는 반드시 self를 지정
        self.bag.append(stuff)  # 클래스 속성 bag에 전달받은 값 stuff를 추가


james = Person()    # 인스턴스 생성
james.put_bag('책')

maria = Person()
maria.put_bag('열쇠')

print(james.bag)
print(maria.bag)
['책', '열쇠']
['책', '열쇠']

- 앗! james와 maria 인스턴스를 각각 만들고 put_bag 메서드를 호출하였는데 같이 합쳐서 보임!!! (혹시 동일 인스턴스인가??)

>>> james is maria
False

출처 : 파이썬 코딩 도장 (dojang.io)

- "클래스 속성"은 클래스에 속해 있으며 모든 인스턴스에서 공유함!

- put_bag 메서드 내에서 클래스 속성 bag에 접근하기 위해 self를 사용했으나, self는 "현재 인스턴스"를 뜻하므로 다음과 같이 명확히 사용한다.

- 사용법 : 클래스.속성

class Person :
    bag = []    # 클래스 속성 생성

    def put_bag(self, stuff) :  # 메서드(클래스 내 함수)의 첫 번째 매개변수는 반드시 self를 지정
        # self.bag.append(stuff)  # 클래스 속성 bag에 전달받은 값 stuff를 추가
        Person.bag.append(stuff)    # 클래스 이름으로 클래스 속성에 접근

james = Person()    # 인스턴스 생성
james.put_bag('책')

maria = Person()
maria.put_bag('열쇠')

# print(james.bag)
# print(maria.bag)

print(Person.bag)   # 클래스 이름으로 클래스 속성에 접근 (가방을 여러 사람이 공유)

 

2. 인스턴스 속성 사용하기

소스 (class_instance_attribute.py) 결과
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)
['책']
['열쇠']

- __init__ 을 통해 인스턴스 속성을 설정하여 해당 인스턴스에만 값을 넣도록 하여 값을 공유하지 않는다!

- 클래스 속성 : 모든 인스턴스가 공유. 인스턴스 전체가 사용해야 하는 값을 저장할 때 사용

- 인스턴스 속성 : 인스턴스별로 독립되어 있음. 각 인스턴스가 값을 따로 저장해야 할 때 사용

 

3. 비공개 클래스 속성 사용하기

- 클래스 속성 만들 때 "__속성" 과 같이 __(밑줄 두 개)로 시작하면 비공개 속성 생성 가능

- 클래스 안에서만 접근 가능하며 클래스 바깥에서는 접근 불가

- 사용법

class 클래스이름 :

    __속성 = 값

소스 (class_private_class_attribute_error.py) 결과
class Knight :
    __item_limit = 10   # 비공개 클래스 속성

    def print_item_limit(self) :
        print(Knight.__item_limit)  # 클래스 안에서만 접근할 수 있음

x = Knight()
x.print_item_limit()    # 10

print(Knight.__item_limit)  # 클래스 바깥에서는 접근 불가 : 에러 유발
10
Traceback (most recent call last):
  File "C:/project/class_private_class_attribute_error.py", line 10, in <module>
    print(Knight.__item_limit)  # 클래스 바깥에서는 접근 불가 : 에러 유발
AttributeError: type object 'Knight' has no attribute '__item_limit'

>> 35.2 정적 메서드 사용하기 <<

- 인스턴스 생성하지 않고 클래스에서 바로 호출가능한 '정적 메서드'와 '클래스 메서드' 확인

- 사용법

class 클래스이름 :

    @staticmethod

    def 메서드 (매개변수1, 매개변수2) :

        코드

- @이 붙은 것을 "데코레이터"라고 부르며, 메서드(함수)에 추가 기능을 구현 시 사용 (Unit 42.에서 자세히 다룸)

소스 (class_static_method.py) 결과
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를 넣지 않은 거지??

- @staticmethod를 사용한 정적 메서드(static method)는 self를 받지 않으므로 인스턴스 속성에는 접근 불가!

-> 정적 메서드는 인스턴스 속성, 인스턴스 메서드가 필요없을 경우 사용!

- 만일 self를 넣으면 TypeError 발생

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)    # 클래스에서 바로 메서드 호출
Traceback (most recent call last):
  File "C:/project/class_static_method.py", line 10, in <module>
    Calc.add(10, 20)    # 클래스에서 바로 메서드 호출
TypeError: add() missing 1 required positional argument: 'b'

- 정적 메서드는 인스턴스의 상태를 변화시키지 않는 메서드를 만들 때 사용함


>> 35.3 클래스 메서드 사용하기 <<

- 클래스 메서드는 메서드 위에 "@classmethod" 사용

- 정적 메서드와 달리 첫 번째 매개변수에 "cls"를 지정해야 함 (cls : class)

- 사용법

class 클래스이름 :

    @classmethod

    def 메서드 (cls, 매개변수1, 매개변수2) :

        코드

소스 (class_class_method.py) 결과
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명 생성되었습니다.
2명 생성되었습니다.

- 클래스 메서드(class method)는 메서드 안에서 클래스 속성, 클래스 메서드에 접근 시 사용

 

● 요약
1. 정적 메서드 : 인스턴스 없이 클래스에서 바로 호출 가능한 메서드. 인스턴스 속성, 인스턴스 메서드 필요 없을 시 사용
2. 클래스 메서드 : 인스턴스 없이 클래스에서 바로 호출 가능한 메서드. 메서드 안에서 클래스 속성, 클래스 메서드 접근 시 사용
3. 클래스 속성 : 모든 인스턴스가 공유. 인스턴스 전체가 사용해야 하는 값을 저장할 때 사용
4. 인스턴스 속성 : 인스턴스별로 독립되어 있음. 각 인스턴스가 값을 따로 저장해야 할 때 사용