메타 클래스 상속

  1. type 클래스 상속
  2. metaclass 속성 사용
  3. 커스텀 메타 클래스 생성

예제

# Ex1
# 커스텀 메타클래스 생성 예제(Type 상속X)

def cus_mul(self, d):
    for i in range(len(self)):
        self[i] = self[i] * d

def cus_replace(self, old, new):
    while old in self:
        self[self.index(old)] = new

# list를 상속받음, 메소드 2개 추가

CustomeList1 = type('CustomList1',
                    (list, ), # 리스트 상속받았기 때문에
                    {'desc': '커스텀 리스트1', 'cus_mul': cus_mul, 'cus_replace': cus_replace})

c1 = CustomeList1([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) #인자값 없으면 List 못받아서 값 뭐냐고 뭐라 할 꺼임
c1.cus_mul(1000)
c1.cus_replace(1000, 7777)

print('Ex1 > ', c1) # Ex1 >  [7777, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000]
print('Ex1 > ', c1.desc)

이런식으로 만드는 기능 함수를 빼놓으면 컴포턴트 방식으로 클래스 만들때 컴포넌트로 하나씩 넣어서 사용할 수 있다. 클래스의 메소드도 나눠 사용할 수 있다.


메타클래스는 99%의 사용자는 전혀 고려할 필요가 없는 흑마법이다.

만약 당신이 이게 정말로 필요할지에 대한 의문을 갖는다면, 필요하지 않습니다.

(이게 진짜로 필요한 사람은 이게 진짜로 필요하다고 알고 있으면서, 왜 필요한지에 대해 설명할 필요가 없는 사람들입니다.)

# Ex2
# 커스텀 메타클래스 생성 예제 (Type 상속 해봄)

# class MetaClassName(type):
#     def __new__(cls, name, bases, namespace):
#         코드 작성

# 실생순서 new -> init -> call
class CustomListMeta(type):
    # 생성된 인스턴스 초기화
    def __init__(self, object_or_name, bases, dict):
        print('__init__ -> ', self, object_or_name, bases, dict)
        super().__init__(object_or_name, bases, dict)
    # 인스턴스 실행
    def __call__(self, *args, **kwargs):
        print('__call__ -> ', self, *args, **kwargs)
        return super().__call__(*args, **kwargs)
    # 클래스 인스턴스 생성(메모리 초기화)
    def __new__(cls, name, bases, namespace):
        print('__new__ -> ', cls, name, bases, namespace)
        namespace['desc'] = '커스텀 리스트 2'
        namespace['cus_mul'] = cus_mul
        namespace['cus_replace'] = cus_replace
        return type.__new__(cls, name, bases, namespace)

CustomList2 = CustomListMeta(
    'CustomList2',
    (list, ),
    {})

c2 = CustomList2([1,2,3,4,5,6,7,8,9,10])
c2.cus_mul(1000)
c2.cus_replace(1000, 7777)

print('Ex2 > ', c2)
print('Ex2 > ', c2.desc)
print('Ex2 > ', dir(c2))

__init__안에서 안에 dict을 잡아채서 코드를 짜서 만들 수 있는데 이런 것을 후킹이라고 한다.

이 실행 순서는 new → init → call 순으로 실행이 된다. 그래서 위와 같이 상속을 올려보내준다.

위와 아래는 똑같은 기능을 한다.