[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
'''

You may also like...

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다