Instance변수는 각각의 Instance마다 독립한 변수이다. 예를 들어, Classs는 몇 개의 Instance를 생성하는 것이 가능하지만, 각각의 Instance 변수는 다른 것으로 취급하는 변수에 값을 대입해도, Instance마다 각각의 값을 보존되어 있다.
Class 변수는 Instance 변수와 달리 모든 Instance 사이에 공유된 값을 가진 변수이다. Class 변수는 Instance를 생성하는 것이 아닌 참고하는 것이 가능하다.
class Counter:
def __init__(self, value=0):
self.value = value
def increment(self, delta=1):
self.value = delta
def decrement(self, value=2):
self.value -= delta
위의 Counter 클래스에는 3개의 인스턴스 메서드로 이루어져 있으며, 각 인스턴스 메서드는 self라는 첫번째 매개 변수를 가지고 있다. self를 통해 인스턴스에 접근하거나 다른 인스턴스 메서드를 호출할 수 있다. 뿐만 아니라 self를 통해, 클래스 속성에 접근하거나 클래스 메서드를 호출할 수도 있다.
@classmethod 데코레이터를 사용해서 클래스에 메서드를 선언하면 해당 메서드는 클래스 메서드가 되며, 첫번쨰 매개 변수로 클래스 인스턴스가 아닌 클래스 자체가 넘어오게 된다.
class User:
def __init__(self, email, password):
self.email = email
self.password = password
@classmethod
def fromTuple(cls, tup):
return cls(tup[0], tup[1])
@classmethod
def fromDict(cls, dic):
return cls(dic["email"], dic["password"])
클래스 메서드는 첫번째 매개변수의 이름은 보통 cls라고 하며, class를 뜻한다. 그리고 cls를 통해 클래스 속성에 접근하거나, 클래스 메서드를 호출할 수 있다. 하지만, 인스턴스 메서드와 달리 인스턴스 속성에 접근하거나 다른 인스턴스 메서드를 호출하는 것은 불가능하다.
정적 메서드는 인스턴스 메서드나 클래스 메서드와 달리 첫번째 매개 변수가 할당되지 않는다. 따라서 정적 메서드 내에서는 인스턴스/클래스 속성에 접근하거나, 인스턴스/클레스 메서드를 호출하는 것이 불가능하다.
class StringUtils:
@staticmethod
def toCamelcase(text):
words = iter(text.split("_"))
return next(words) + "".join(i.title() for i in words)
@staticmethod
def toSnakecase(text):
letters = ["_"+i.lower() if i.isupper() else i for i in text]
return "".join(letters).lstrip("_")
이 두 개의 메서드는 매개 변수로 넘어온 문자열에만 의존하는 순수한(pure) 함수이기 때문에 굳이 클래스의 일부로 선언할 필요는 없지만, 이렇게 비슷한 류의 여러 유틸리티 메서드를 하나의 클래스의 묶어두고 싶을 때 정적 메서드로 선언할 수 있다.