Class Method Inheritance in Python

Tags:

The Static Method Thing

class Cacheable:
    _cache = {}
    def create_cached(cls, value):
        if not cls._cache.has_key(value):
            print 'cache miss'
            rslt = cls(value)
            cls._cache[value] = rslt
        else:
            print 'cache hit'
            rslt = cls._cache[value]
        return rslt
    create_cached = classmethod(create_cached) 

class X(Cacheable):
    def __init__(self, value):
        self.value = value

x = X.create_cached('test')  # X instance created
x = X.create_cached('test2') # X instance created
x = X.create_cached('test')  # X instance taken from cache

classmethod를 사용하면 메소드가 상속되었을때 derived class를 클래스 메소드의 첫번째 인자로 줍니다. 그래서 위에처럼 이를 cls로 받아서 생성자를 부른다던가 – cls(value) 부분 – 할 수 있음. 호.. 신기하군요. C++의 CRTP와 비슷해보이네요.

반면 자바처럼 static method를 만들기 위해 classmethod를 쓰는 것은 반대하며 대신 별도의 파일로 메소드들을 선언하면 그것이 곧 모듈이다..라는 군요. 그러니까

>>> class Foo:
...     def bar(cls):
...             print cls
...     bar = classmethod(bar)
...
>>> Foo.bar()
__main__.Foo
>>>

이렇게 하지 말란거죠. (참고: 위에처럼 bar가 중복 사용되면 메소드가 가려지고 변수가 살아남음) 된다고 해서 마구해서는 안된다..라는 것이 또 파이썬의 중요한 핵심 축인 듯. 예를 들어, 파이썬에서도 core class들을 수정할 수 있으나 이런 형태는 monkey patch 라고 불리며 피해야 할 코딩패턴이라는군요. 반면 루비의 경우엔 core class의 수정이 가능하다는 것이 중요한 코딩 테크닉으로 쓰이는데, 그와 같은 예가 바로 이전에 포스팅한 Ruby Linguistics가 있죠. 이런 것은 커뮤니티의 마인드 차이가 참 큰 듯..