type 외에도 우리는 우리가 원하는 메타클래스를 만들 수도 있다
__metaclass__Foo 클래스를 만들기 위해 해당 메타클래스를 사용합니다. 발견하지 못한 경우에는 클래스를 만들기 위해 type을 사용
우리가 보통 메타클래스를 introspection, manipulating, inheritance, __dict__와 같은 변수 등을 사용하여 복잡한 무언가를 만드는 데 사용
metaclass 속성은 상속되지 않는다는 점
현재 컨텍스트와 알맞는 클래스를 만들기 위해 API와 같은 곳에 커스텀 메타클래스를 사용
metaclass callable 하기만 하면 댐
메타클래스를 이용하면 다음 일들이 쉬워집니다:
- 클래스 생성 가로채기(intercept)
- 클래스 수정하기(modify)
- 수정된 클래스 반환하기
API 개발에 많이 사용가능
function style
__metaclass__
# 메타클래스는 우리가 보통 `type`에 전달하는 객체와 같은 객체를 받습니다. def upper_attr(future_class_name, future_class_parents, future_class_attr): """ 대문자로 변환된 속성의 리스트와 함께 클래스 객체를 반환합니다. """ # '__'로 시작하지 않는 모든 객체를 가져와 대문자로 변환합니다. uppercase_attr = {} for name, val in future_class_attr.items(): if not name.startswith('__'): uppercase_attr[name.upper()] = val else: uppercase_attr[name] = val # `type`으로 클래스를 생성합니다. return type(future_class_name, future_class_parents, uppercase_attr) __metaclass__ = upper_attr # 이리하여 모듈 내에 있는 모든 클래스가 영향을 받게 됩니다. class Foo(): # 하지만 글로벌 메타클래스는 object와 함께 작동하지 않습니다 # 하지만 우리는 이 클래스에만 영향을 주고자 여기에 __metaclss__를 정의하면 # object 자식(children)과 함께 작동하게 됩니다. bar = 'bip' print(hasattr(Foo, 'bar')) # Out: False print(hasattr(Foo, 'BAR')) # Out: True f = Foo() print(f.BAR) # Out: 'bip'
class style
type.__new__
class UpperAttrMetaclass(type): def __new__(cls, clsname, bases, dct): uppercase_attr = {} for name, val in dct.items(): if not name.startswith('__'): uppercase_attr[name.upper()] = val else: uppercase_attr[name] = val return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)
Python의 metaclasses(메타클래스) 이해하기
이 글은 메타클래스에 대해 가장 잘 설명되어있다고 생각되는 Stackoverflow 답변을 번역한 문서입니다. 클래스를 객체로 메타클래스를 이해하기 전에 Python의 클래스에 대한 완전한 이해가 필요합니다. 또한 Python은 Smalltalk 언어에서 따온 매우 특별한 클래스 구성이 존재합니다. 대부분의 언어에서 클래스는 어떻게 객체를 생성할지에 대해 정의하는 코드조각일 뿐입니다. 물론 Python에서도 그렇습니다: >>> class
https://tech.ssut.me/understanding-python-metaclasses/

