본문 바로가기

Python_programming/초중급편

파이썬 클래스 사용하기2: 클래스 속성과 정적, 클래스 메서드

앞에서 인스턴스 속성을 사용하는 법과 self 등에 대해 배웠습니다. 

이번 시간에는 클래스 속성이랑 정적, 클래스 메서드 이렇게 3가지를 배워 보겠습니다!

 

사실 속성에는 클래스 속성과 인스턴스 속성 2가지 종류가 있습니다. init 메서드에서 만들었던 속성인스턴스 속성입니다.

이번에 배울 클래스 속성은 

 

class 클래스이름:

    속성 = 값 

 

형태로 입력해주시면 됩니다. 

 

james.bag 과 maria.bag을 출력해보면 넣었던 물건이 합쳐져서 나옵니다. 즉, 클래스 속성은 클래스에 속해 있으며 모든 인스턴스에서 공유됩니다.

 

출처:https://dojang.io/mod/page/view.php?id=2378

 

put_bag 메서드에서 클래스 속성 bag에 접근할 때 self를 사용했습니다. 사실 self는 현재 인스턴스를 뜻하므로 클래스 속성을 지칭하기에는 조금 모호합니다. 그래서 클래스 속성에 접근할 때는 다음과 같이 클래스 이름으로 접근하면 좀 더 코드가 명확해집니다.

 

- 클래스.속성

 

Person.bag 이라고 하니 클래스 Person에 속한 bag 속성이라는 것을 바로 알 수 있습니다. 클래스 바깥에서도 클래스 이름으로 접근하는 것을 위 코드에서 확인할 수 있습니다.

 

- 속성, 메서드 이름을 찾는 순서 - 

 

 

파이썬에서는 속성, 메서드 이름을 찾을 때 인스턴스, 클래스 순으로 찾습니다. 그래서 인스턴스 속성이 없으면 클래스 속성을 찾게 되므로 james.bag, maria.bag도 문제 없이 동작합니다. 겉보기에는 인스턴스 속성을 사용하는 것 같지만 실제로는 클래스 속성입니다. 인스턴스와 클래스에서 __dict__ 속성을 출력해보면 현재 인스턴스와 클래스의 속성을 딕셔너리로 확인할 수 있습니다.

 

jaees.bag을 사용했을 때 클래스 속성을 찾는 과정은 다음과 같습니다. 

 

출처: https://dojang.io/mod/page/view.php?id=2378

다음으로 인스턴스 속성 사용에 대해 이야히 해보겠습니다.

 

james.bag과 curry.bag을 출력하면 각자 넣은 물건만 출력됩니다. 즉, 인스턴스 속성은 인스턴스별로 독립되어 있으며 서로 영향을 주지 않습니다. 

 

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

35.1.3 비공개 클래스 속성 

 

클래스 속성을 만들 때 __속성 과 같이 __ (밑줄 두 개)로 시작하면 비공개 속성이 됩니다. 이 때 클래스 안에서만 접근할 수 있고, 클래스 바깥에서는 접근할 수 없습니다.

 

class 클래스이름:

    __속성 = 값 # 비공개 클래스 속성

 

 

실행을 해보면 클래스 Knight의 비공개 클래스 속성 __item_limit는 클래스 안의 print_item_limit 메서드에서만 접근할 수 있고, 클래스 바깥에서 접근하면 에러가 발생합니다.  이처럼 비공개 클래스 속성은 클래스 바깥으로 드러내고 싶지 않은 값에 사용합니다.

 

35.2 정적 메서드

 

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

 

class 클래스이름:

    @staticmethod

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

         코드

 

 

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

<데코레이터는 조만간 따로 포스팅을 하겠습니다 :) >

 

Calc 클래스에서 @staticmethod를 붙여서 add 메서드와 mul 메서드를 만들었습니다. 정적 메서드를 호출할 때는 위 코드처럼   클래스에서 바로 메서드를 호출하면 됩니다.

 

  • 클래스.메서드()

정적 메서드self를 받지 않으므로 인스턴스 속성에는 접근할 수 없습니다. 그래서 보통 정적 메서드는 인스턴스 속성, 인스턴스 메서드가 필요 없을 때 사용합니다. 여기서 만든 Calc 클래스에 들어있는 add,mul 메서드는 숫자 2개를 받아서 더하거나 곱할뿐 인스턴스 속성은 필요하지 않습니다.

 

정적 메서드는 메서드의 실행이 외부 상태에 영향을 끼치지 않는 순수함수를 만들 때 사용합니다. 순수 함수는 부수 효과가 없고 입력 값이 같으면 언제나 같은 출력 값을 반환합니다. 즉, 정적 메서드는 인스턴스의 상태를 변화시키지 않는 메서드를 만들 때 사용합니다.

 

위처럼 인스턴스의 내용을 변경해야 할 때는 update와 같이 인스턴스 메서드로 작성하면 되고, 인스턴스 내용과는 상관없이 결과만 구하면 될 때는 set.union과 같이 정적 메서드로 작성하면 됩니다.

 

35.3 클래스 메서드

 

클래스 메서드는 다음과 같이 메서드 위에 @classmethod를 붙입니다. 이때 클래스 메서드는 첫 번째 매개변수에 cls를 지정해야 합니다(cls class에서 따왔습니다).

 

class 클래스이름:

    @classmethod

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

         코드

 

먼저 인스턴스가 만들어질 때마다 숫자를 세야 하므로 __init__ 메서드에서 클래스 속성 count에 1을 더해줍니다. 물론 클래스 속성에 접근한다는 것을 명확하게 하기 위해 Person.count와 같이 만들어줍니다.

 

다음으로 @classmethod를 붙여서 클래스 메서드를 만듭니다. 클래스 메서드는 첫 번째 매개변수가 cls인데 여기에는 현재 클래스가 들어옵니다. 따라서 cls.count처럼 cls로 클래스 속성 count에 접근할 수 있습니다.

 

Person으로 인스턴스를 두 개 만들었으므로 print_count를 호출해보면 '2명 생성되었습니다.'가 출력됩니다. 물론 print_count는 클래스 메서드이므로 Person.print_count()처럼 클래스로 호출해줍니다.

 

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

 

(아래 코드 참고) 특히 cls를 사용하면 메서드 안에서 현재 클래스의 인스턴스를 만들 수도 있습니다. 즉, cls는 클래스이므로 cls()는 Person()과 같습니다. 클래스 메서드를 호출할 때 마다 인스턴스가 만들어지고 이를 통해 클래스 속성인 count에 접근해서 +1을 하라는 매직메서드의 기능을 수행됨을 확인할 수 있습니다.

 

 

이번 시간에 다룬 클래스 속성과 정적 메서드, 클래스 메서드는 중요한 내용입니다. 특히 클래스 속성은 전에 다룬 인스턴스 속성과 같이 보면서 차이를 명확히 정리하면 좋습니다. 이번 포스팅도 길벗 출판사 '파이썬 코딩도장'을 참고해서 작성했습니다. 

 

다음 시간에는 클래스 상속에 대해 다뤄보겠습니다!