# 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 순으로 실행이 된다. 그래서 위와 같이 상속을 올려보내준다.
위와 아래는 똑같은 기능을 한다.