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

지금까지 간단하게 클래스를 만들고 속성과 메서드를 사용해봤습니다. 이번에는 클래스에 속해 있는 클래스 속성에 대해 알아보겠습니다. 그리고 인스턴스를 만들지 않고 클래스로 호출하는 정적 메서드와 클래스 메서드도 알아보겠습니다.

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

지금까지 클래스의 속성을 사용해봤습니다. 사실 속성에는 두 가지 종류가 있습니다. 클래스 속성과 인스턴스 속성이 있는데 __init__ 메서드에서 만들었던 속성은 인스턴스 속성입니다.

그럼 이번에는 클래스 속성을 사용해보겠습니다. 클래스 속성은 다음과 같이 클래스에 바로 속성을 만듭니다.

def 클래스이름:
    속성 = 

이제 간단하게 사람 클래스에 클래스 속성으로 가방 속성을 넣고 사용해보겠습니다. 다음과 같이 Person 클래스에 바로 bag 속성을 넣고, put_bag 메서드를 만듭니다. 그리고 인스턴스 두 개를 만든 뒤 각각 put_bag 메서드를 사용합니다.

class_class_attribute.py

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)

실행 결과

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

가방에 물건을 넣는 간단한 동작을 만들었습니다. 그런데 결과가 좀 이상하죠? jamesmaria 인스턴스를 만들고 각자 put_bag 메서드로 물건을 넣었는데, james.bagmaria.bag을 출력해보면 넣었던 물건이 합쳐져서 나옵니다. 즉, 클래스 속성은 클래스에 속해 있으며 모든 인스턴스에서 공유합니다.

그림 37-1 클래스 속성
그림 37 1 클래스 속성

put_bag 메서드에서 클래스 속성 bag에 접근할 때 self를 사용했습니다. 사실 self는 현재 인스턴스를 뜻하므로 클래스 속성을 지칭하기에는 조금 모호합니다.

class Person:
    bag = []
 
    def put_bag(self, stuff):
        self.bag.append(stuff)

그래서 클래스 속성에 접근할 때는 다음과 같이 클래스 이름으로 접근하면 좀더 코드가 명확해집니다.

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

Person.bag이라고 하니 클래스 Person에 속한 bag 속성이라는 것을 바로 알 수 있습니다. 마찬가지로 클래스 바깥에서도 다음과 같이 클래스 이름으로 클래스 속성에 접근하면 됩니다.

print(Person.bag)

파이썬에서는 속성, 메서드 이름을 찾을 때 인스턴스, 클래스 순으로 찾습니다. 그래서 인스턴스 속성이 없으면 클래스 속성을 찾게 되므로 james.bag, maria.bag도 문제 없이 동작합니다. 겉보기에는 인스턴스 속성을 사용하는 것 같지만 실제로는 클래스 속성입니다.

그럼 가방을 여러 사람이 공유하지 않으려면 어떻게 해야 할까요? 그냥 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)

실행 결과

['책']
['열쇠']

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

정리하자면 모든 인스턴스가 값을 공유해야 할 때는 클래스 속성을 사용하고, 각 인스턴스가 값을 따로 저장해야 할 때는 인스턴스 속성을 사용하면 됩니다.

참고 | 비공개 클래스 속성

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

def 클래스이름:
    __속성 =     # 비공개 클래스 속성
참고 | 클래스와 메서드의 독스트링 사용하기

함수와 마찬가지로 클래스와 메서드도 독스트링을 사용할 수 있습니다. 다음과 같이 클래스와 메서드를 만들 때 :(콜론) 바로 다음 줄에 """ """(큰따옴표 세 개) 또는 ''' '''(작은따옴표 세 개)로 문자열을 입력하면 됩니다. 그리고 클래스의 독스트링은 클래스.__doc__ 형식으로 사용하고, 메서드의 독스트링은 클래스.메서드.__doc__ 또는 인스턴스.메서드.__doc__ 형식으로 사용합니다.

class Person:
    '''사람 클래스입니다.'''
    
    def greeting(self):
        '''인사 메서드입니다.'''
        print('Hello')
 
print(Person.__doc__)             # 사람 클래스입니다.
print(Person.greeting.__doc__)    # 인사 메서드입니다.
 
maria = Person()
print(maria.greeting.__doc__)     # 인사 메서드입니다.