파이썬의 메타클래스를 공부하다가
좀 애매했던것들을 확실하게 정리하게 되었다.
일단 기본적인것을 먼저 짚고 좀더 자세히 보자.
1. __init__(self, *args, **kwargs)
이것을 생성자로 알고있는 사람이 많다.
하지만 엄밀히 따지면 초기화 함수이다.
여기서 self는 생성된 인스턴스를 의미한다.
2. __new__(cls, *args, **kwargs)
이것이 진정한 생성자 함수이다.
__init__보다 먼저 실행된다.
즉 인스턴스 생성시 __new__가 실행되고 __init__ 가 실행된다.
이건 클래스함수(@classmethod)이기 때문에 첫번째 인자가 self가 아니라 cls를 적어준다.
cls는 클래스 자체를 의미한다.
3. __call__(self, *args, **kwargs)
이것은 인스턴스가 호출될때 발생한다.
4. 메타클래스
메타클래스란 클래스 객체를 생성하는 클래스이다.
클래스는 메타클래스의 인스턴스인 셈이다.
반대로 메타클래스는 클래스의 클래스이다. (읭?! ㅎ)
클래스의 인스턴스 == 메타클래스의 인스턴스의 인스턴스 (읭?! ㅎㅎ)
파이썬에서 기본 메타클래스는 type이다.
5. type
type은 어떤 객체의 자료형을 리턴한다.
달리말하면 해당 객체가 어느 클래스로부터 비롯되었는지 (인스턴스화 하였는지) 나타낸다.
(파이썬에서 모든것은 객체이다)
아래 코드를 보자.
1 2 3 4 5 6 7 8 9 | class Sample(): pass type(Sample) # type s = Sample() type(s) # __main__.Sample | cs |
5.1 type (메타클래스)
또한 type은 클래스를 만들 수 있다.
syntax는
1 | type('클래스이름 string', (상속받는 클래스 tuple), {필드 및 메서드 dict}) | cs |
따라서 type을 상속하는 클래스는 메타클래스가 되는데
그 메타클래스를 이용해 위와 같은 문법으로 클래스를 만들 수 있다.
1 2 3 4 5 6 7 8 9 | class CustomMeta(type): pass Sample = CustomMeta() # 위와 아래는 똑같이 Sample이라는 클래스를 생성한다. Sample = CustomMeta('Sample', (), {}) #__main__.Sample | cs |
6. Singleton
이제 다왔다.
메타클래스를 호출하면 클래스가 나온다.
클래스는를 호출하면 인스턴스를 생성할 수 있다.
클래스를 호출한다는것은 메타클래스의 __call__ 메서드를 호출하는것과 같다.
따라서 메타클래스의 __call__메서드에서 싱글톤 작업을 수행하면 된다.
1 2 3 4 5 6 7 8 9 10 | class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] class CustomClass(metaclass=Singleton): pass | cs |
__call__ 메서드의 첫번째 파라미터가 self가 아니라 cls인 이유는,
메타클래스의 인스턴스가 클래스기 때문에 cls이라고 쓴것이다. 사실상 self와 똑같이 작동한다.
보통 클래스를 만들면 그 클래스는 object 객체(클래스)를 상속하고 type을 메타클래스로 사용하게 된다.
1 2 3 4 5 6 7 8 | class MyClass(): pass class MyClass(object, metaclass=type): pass # 위와 아래의 클래스는 같은 기능을 수행한다. | cs |
참고1: https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python
참고2: https://wikidocs.net/3693
No comments:
Post a Comment