Python Custom metaclass


type 외에도 우리는 우리가 원하는 메타클래스를 만들 수도 있다
`__`**`metaclass__`**
Foo 클래스를 만들기 위해 해당 메타클래스를 사용합니다. 발견하지 못한 경우에는 클래스를 만들기 위해 type을 사용
우리가 보통 메타클래스를 introspection, manipulating, inheritance, __dict__와 같은 변수 등을 사용하여 복잡한 무언가를 만드는 데 사용
**metaclass** 속성은 상속되지 않는다는 점
현재 컨텍스트와 알맞는 클래스를 만들기 위해 API와 같은 곳에 커스텀 메타클래스를 사용
metaclass callable 하기만 하면 댐
메타클래스를 이용하면 다음 일들이 쉬워집니다:
- 클래스 생성 가로채기(intercept)
- 클래스 수정하기(modify)
- 수정된 클래스 반환하기
 API 개발에 많이 사용가능


### function style
__metaclass__
```type# 메타클래스는 우리가 보통 `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: Falseprint(hasattr(Foo, 'BAR'))# Out: Truef = Foo()print(f.BAR)# Out: 'bip'```


### class style
type.__new__
```typeclass 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(메타클래스) 이해하기](https://tech.ssut.me/understanding-python-metaclasses/)






