[Python] 클래스 함수(class method)와 덕 타이핑 그리고 특수 메서드


Study/Python  2019. 12. 18. 09:00

안녕하세요. 명월입니다.


이 글은 Python에서 클래스 함수(class method)와 덕 타이핑 그리고 특수 메서드에 관한 글입니다.


예전에 Python 클래스와 함수에 대해 설명한 적이 있습니다.

링크 - [Python] 클래스 (Class)

링크 - [Python] 함수(function) - 인라인 함수, callback, 람다 함수 그리고 클로져


일반적인 클래스에서 함수를 사용하는 방법은 함수에 첫번째 파리미터에 self를 넣고 호출을 할 때 클래스를 생성(인스턴스화)하고 호출하면 문안하게 사용됩니다.

class TestClass():
  def __init__(self):
    pass;
  def call_function(self):
    print("call");

obj = TestClass();
obj.call_function();

Python에서는 클래스 함수라고 이야기하지만 다른 언어에서는 static함수라고 하는 함수가 있습니다.

class TestClass():
  # 이 변수는 static 변수입니다. 변수명 앞에 언더바(_) 두개를 붙여야 private가 됩니다.
  __count = 0;
  def __init__(self):
    # static 변수이기 때문에 self로 접근하는 것이 아닙니다.
    TestClass.__count = TestClass.__count + 1;
  def call_function(self):
    print("call");
    
  # classmethod 데코레이터를 사용합니다. 그냥 TestClass의 static함수입니다.
  @classmethod
  def generated_class_count(cls):
    print(cls.__count);

# 인스턴스를 생성할 때마다 __count는 1씩 증가합니다.
obj = TestClass();
obj1 = TestClass();
obj2 = TestClass();

TestClass.generated_class_count();

이번에는 덕 타이핑입니다. 덕 타이핑은 C#의 dynamic 변수와 유사하고 javascript의 콜백 함수와 비슷합니다.

# TestClass1 클래스 안에 call_function 함수가 존재
class TestClass1():
  def __init__(self):
    pass;
  def call_function(self):
    print("TestClass1 call");

# TestClass2 클래스 안에 call_function 함수가 존재
class TestClass2():
  def __init__(self):
    pass;
  def call_function(self):
    print("TestClass2 call");

# TestClass3 클래스 안에 call_function 함수가 존재
class TestClass3():
  def __init__(self):
    pass;
  def call_function(self):
    print("TestClass3 call");

# obj의 call_function 함수를 호출.
def call_function(obj):
  obj.call_function();

# 인스턴스 생성  
obj1 = TestClass1();
obj2 = TestClass2();
obj3 = TestClass3();

# 각 인스턴스를 call_function를 통해 클래스 안의 call_function함수를 호출한다.
call_function(obj1);
call_function(obj2);
call_function(obj3);

Python에서는 인터페이스가 존재하지 않으니 위와 같은 차선책으로 다형성을 구현한 듯 싶네요. 근데 오히려 인터페이스가 없는 환경에서 위와 같이 작성하면 오히려 버그 발생이나 가독성이 더 떨어질 듯 싶은데..

개인적인 생각입니다만 저런 식으로 작성하고 나중에 TestClass3에서 call_function를 수정하거나 지운다면 치명적인 에러가 발생할 수 있습니다. 오히려 그 때가 되면 소스를 뒤져가며 다형성 함수를 찾아 수정해야 합니다.

개인적인 생각입니다.


그리고 특수 메서드입니다. 특수 메서드는 Java나 C#에서 최상위 클래스 Object에 선언된 기본 함수를 뜻합니다. ToString()과 비슷한 거죠.

이게 종류가 굉장히 많은데 어느 분이 잘 정리해 놓은게 있습니다.

링크 - https://codeonweb.com/entry/1cab851f-da6a-4ce5-892b-513d84c53f3b

링크 - https://docs.python.org/3/reference/datamodel.html#special-method-names


여기서 자주사용하는 __eq__와 __ne__, __str__, __repr__, __len__ 정도만 소개하겠습니다.

class TestClass():
  def __init__(self, data):
    self.data = data;
  def __eq__(self, obj):
    print("__eq__ call");
    return self.data == obj.data;
  def __ne__(self, obj):
    print("__ne__ call");
    return self.data != obj.data;
  def __str__(self):
    print("__str__ call");
    return str(self.data);
  def __len__(self): 
    print("__len__ call");
    return len(self.data);
    
obj1 = TestClass("a");
obj2 = TestClass("b");

# __eq__가 호출된다.
print(obj1 == obj2);
# __ne__가 호출된다.
print(obj1 != obj2);
# __str__가 호출된다.
print(obj1);
# __len__가 호출된다.
print(len(obj1));

여기까지 Python에서 클래스 함수(class method)와 덕 타이핑 그리고 특수 메서드에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.