[Python]Meta Class(메타 클래스)
파이썬의 Meta Class에 대해서 알아보자.
"""
Meta Class(1)
메타 클래스
1. 클래스를 만드는 역할 -> 의도하는 방향으로 클래스 커스텀
2. 프레임워크 작성 시 필수
3. 동적 생성(type), 커스텀 생성(type) 함수
4. 커스텀 클래스 -> 검증클래스 등
5. 엄격한 class 사용 요구, 메소드 오버라이드 요구
"""
# Ex1
class SampleA:
pass
obj1 = SampleA() # 변수에 할당, 복사 가능, 새로운 속성 추가, 함수의 인자로 넘기기 가능
# obj1.new_property = "aa" # <-- 가능하다.
# obj1 -> SampleA instance
# SampleA -> type meta class
# type -> type meta class
print('Ex1 > ', obj1.__class__)
print('Ex1 > ', type(obj1))
print('Ex1 > ', obj1.__class__ is type(obj1))
"""
Ex1 > <class '__main__.SampleA'>
Ex1 > <class '__main__.SampleA'>
Ex1 > True
"""
print('Ex1 > ', obj1.__class__.__class__)
print('Ex1 > ', obj1.__class__.__class__ is type(obj1).__class__)
print(type.__class__)
"""
Ex1 > <class 'type'>
Ex1 > True
<class 'type'>
"""
# Ex2
# type meta(Ex1 증명)
n = 10
d = {'a': 10, 'b': 20}
class SampleB:
pass
obj2 = SampleB()
for o in (n, d, obj2):
print(f'Ex2 : {type(o)}, {type(o) is o.__class__}, {o.__class__.__class__}')
"""
Ex2 : <class 'int'>, True, <class 'type'>
Ex2 : <class 'dict'>, True, <class 'type'>
Ex2 : <class '__main__.SampleB'>, True, <class 'type'>
"""
print()
for t in int, float, list, tuple:
print(f'Ex2 : {type(t)}')
"""
Ex2 : <class 'type'>
Ex2 : <class 'type'>
Ex2 : <class 'type'>
Ex2 : <class 'type'>
"""
print(type(type))
"""
<class 'type'>
"""
"""
Meta Class(2)
동적으로 클래스 및 메서드 생성
"""
# Ex1 : 동적 클래스 생성예제
# Name(이름), Bases(상속), Dct(속성, 메서드)
s1 = type('Sample1', (), {})
print('Ex1 > ', s1)
print('Ex1 > ', type(s1))
print('Ex1 > ', s1.__base__)
print('Ex1 > ', s1.__dict__)
print()
"""
Ex1 > <class '__main__.Sample1'>
Ex1 > <class 'type'>
Ex1 > <class 'object'>
Ex1 > {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Sample1' objects>, '__weakref__': <attribute '__weakref__' of 'Sample1' objects>, '__doc__': None}
"""
# Ex2 : 동적생성 + 상속
class Parent1:
pass
s2 = type('Sample2', (Parent1,), dict(attr1=100, attr2='hi'))
print('Ex2 > ', s2)
print('Ex2 > ', type(s2))
print('Ex2 > ', s2.__base__)
print('Ex2 > ', s2.__dict__)
print('Ex2 > ', s2.attr1, s2.attr2)
print()
"""
Ex2 > <class '__main__.Sample2'>
Ex2 > <class 'type'>
Ex2 > <class '__main__.Parent1'>
Ex2 > {'attr1': 100, 'attr2': 'hi', '__module__': '__main__', '__doc__': None}
Ex2 > 100 hi
"""
# Ex3 : 동적 클래스 생성 + 메서드
class SampleEx:
attr1 = 30
attr2 = 100
def add(self, m, n):
return m + n
def mul(self, m, n):
return m * n
ex = SampleEx()
print('Ex3 > ', ex.attr1)
print('Ex3 > ', ex.attr2)
print('Ex3 > ', ex.add(1, 3))
print('Ex3 > ', ex.mul(11, 5))
print()
"""
Ex3 > 30
Ex3 > 100
Ex3 > 4
Ex3 > 55
"""
s3 = type('Sample3', (object,), {"attr1": 30, "attr2": 100, "add": lambda x, y: x + y, "mul": lambda x, y: x * y})
print('Ex4 > ', s3.attr1)
print('Ex4 > ', s3.attr2)
print('Ex4 > ', s3.add(1, 3))
print('Ex4 > ', s3.mul(11, 5))
print()
"""
Ex4 > 30
Ex4 > 100
Ex4 > 4
Ex4 > 55
"""
"""
Python Advanced - Meta class
1. type클래스 상송
2. metaclass 속성사용
3. 커스텀 메타클래스 생성
"""
# 예1 : 커스텀 메타 클래스 생성예제(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개 추가
CustomList1 = type(
'CustomList1',
(list,),
{
'desc': '커스텀 리스트1',
'cus_mul': cus_mul,
'cus_replace': cus_replace
}
)
c1 = CustomList1([1, 2, 3, 4, 5, 6, 7])
c1.cus_mul(1000)
print('예1 : cus_mul > ', c1)
'''
예1 : cus_mul > [1000, 2000, 3000, 4000, 5000, 6000, 7000]
'''
c1.cus_replace(1000, 9999)
print('예1 : cus_replace > ', c1)
print('예1 : dir > ', dir(c1))
'''
예1 : cus_replace > [9999, 2000, 3000, 4000, 5000, 6000, 7000]
예1 : dir > ['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'append', 'clear', 'copy', 'count', 'cus_mul', 'cus_replace', 'desc', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
'''
print()
# 예2 : 커스텀 메타 클래스 생성예제(Type 상속O)
# class MetaClassName(type):
# def __new__(metacls, name, bases, namespace):
# pass
# new -> init -> call 순으로 호출됨
class CustomListMeta(type):
# 클래스 인스턴스 생성(메모리 초기화)
def __new__(metacls, name, bases, namespace):
print('__new__ -> ', metacls, name, bases, namespace)
namespace['desc'] = '커스텀 리스트2'
namespace['cus_mul'] = cus_mul
namespace['cus_replace'] = cus_replace
return type.__new__ (metacls, name, bases, namespace)
# 생성된 인스턴스 초기화
def __init__(cls, object_or_name, bases, dict_value):
print('__init__ -> ', cls, object_or_name, bases, dict_value)
super().__init__(object_or_name, bases, dict_value)
# 인스턴스 생성
def __call__(cls, *args, **kwargs):
print('__call__ -> ', cls, *args, **kwargs)
return super().__call__(*args, **kwargs)
CustomList2 = CustomListMeta(
'CustomList2',
(list,),
{}
)
c2 = CustomList2([1, 2, 3, 4, 5, 6, 7, 8, 9])
print()
'''
__new__ -> <class '__main__.CustomListMeta'> CustomList2 (<class 'list'>,) {}
__init__ -> <class '__main__.CustomList2'> CustomList2 (<class 'list'>,) {'desc': '커스텀 리스트2', 'cus_mul': <function cus_mul at 0x1010c1280>, 'cus_replace': <function cus_replace at 0x101080940>}
__call__ -> <class '__main__.CustomList2'> [1, 2, 3, 4, 5, 6, 7, 8, 9]
'''
c2.cus_mul(1000)
print('예2 : cus_mul > ', c2)
c2.cus_replace(1000, 7777)
print('예2 : cus_replace > ', c2)
print('예2 : desc > ', c2.desc)
'''
예2 : cus_mul > [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000]
예2 : cus_replace > [7777, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000]
예2 : desc > 커스텀 리스트2
'''
최신 댓글