Meta Class

EBAB!·2024년 1월 21일
0
post-custom-banner

메타클래스는 클래스의 클래스라고 표현한다.
보통 클래스는 인스턴스를 생성하는 방법을 정의하는 것처럼 템플릿같은 용도로 사용한다.

메타클래스는 그 대상이 클래스가 된다고 생각하면 된다. 클래스가 어떻게 생성되고 동작할 지 정의하는 역할을 한다. 기본적으로 모든 파이썬 클래스는 type이라는 내장 메타클래스를 사용하여 생성됩니다.

즉, 메타클래스는 내가 의도하는 방향으로 클래스를 커스텀하는 것이다.

type

우리가 흔히 타입을 알기 위해 사용하는 type함수는 명확히 어떤 것을 반환하는 것인지 알고 넘어가자.

class SampleA(): # Class == Object
    pass

obj1 = SampleA() # 변수에 할당, 복사 가능, 새로운 속성, 함수의 인자로 넘기기 가능

# obj1 -> SampleA instance
# SampleA -> type metaclass
# type -> type metaclass
print(obj1.__class__)  # <class '__main__.SampleA'>
print(type(obj1))  # <class '__main__.SampleA'>
print('Ex1 > ', obj1.__class__ is type(obj1))  # True

코드를 보면 알 수 있듯이 type 함수가 반환하는 것은 해당 객체(인스턴스)의 __class__(본래의 원형)이다.

그럼 type함수에 본래의 클래스를 넣으면 어떻게 되는지 알면 메타클래스에 대해 알 수 있다.

print(type(SampleA))  # <class 'type'>

for cls in (int, str, float, dict, tuple):
	print(type(cls)))
"""
<class 'type'>
<class 'type'>
<class 'type'>
<class 'type'>
<class 'type'>
"""

위를 보면 알 수 있는 것이 모든 클래스의 원형은 type이라는 메타클래스인 것이다.


type을 이용한 클래스 동적 생성

tpye(Name(이름), Bases(상속), Dct(속성,메소드))

s1 = type('Sample1', (), {})

print('Ex1 > ', s1)  # '__main__.Sample1'
print('Ex1 > ', type(s1))  # <class 'type'>
print('Ex1 > ', s1.__base__)  # <class 'object'>
print('Ex1 > ', s1.__dict__)  # {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'sample1' objects>, '__weakref__': <attribute '__weakref__' of 'sample1' objects>, '__doc__': None}

위 방식처럼 type을 이용하여 미리 정의된 클래스가 아니라 코드로 클래스가 동적으로 정의될 수 있다.
type클래스의 인자 순서대로 클래스명, 상속받는 객체, 속성 및 메소드 를 받게된다.

특정 클래스를 상속

class Parent1:
    pass

s2 = type(
        'Sample2', 
        (Parent1,), 
        dict(attr1=100, attr2='hi')
    )
    
print(s2)  # <class '__main__.Sample2'>
print(type(s2))  # <class 'type'>
print(s2.__base__)  # <class '__main__.Parent1'>
print(s2.__dict__)  # {'attr1': 100, 'attr2': 'hi', '__module__': '__main__', '__doc__': None}
print(s2.attr1, s2.attr2)  # 100 hi

특정 메소드 할당

class SampleEx:  
    attr1 = 30
    attr2 = 100
    
    def add(self, m, n):
        return m + n

    def mul(self, m, n):
        return m * n


s3 = type(
        'Sample3', 
        (object, ), # 생략 가능
        dict(attr1=30, attr2=100, add=lambda x, y: x + y, mul=lambda x, y: x * y)
    )

위에서 s3와 SmapleEx의 인스턴스는 완전히 동일한 기능을 한다.

profile
공부!
post-custom-banner

0개의 댓글