Skip to content

배토의 개발일지

나를위한 단편적 기억들의 기록

Menu
  • 안드로이드
  • 코틀린
  • Godot
  • 블렌더
  • git
  • 게임제작일지
  • 기타
Menu

Python : metaclass

Posted on 2020년 3월 25일2020년 4월 16일 by batmask

metaclass는 일반적인 파이썬 사용에는 필요없는 조금은 깊이 들어가는 내용이지만, OOP적 접근을 위해 알 필요가 있어보인다. stackoverflow에 달린 설명 참조.

파이썬에서는 모든게 object이다. 클래스도 object로 생성이 되고 instance화 시킬 때, 이 object가 복사되면서 __init__ 루틴을 타게된다. 일반적인 인스턴스에 대해 어떤 클래스로부터 왔는지 알아보는 함수에 type()을 쓸 수 있는데, 그렇다면 클래스는 어떤 타입일까?

class Foo:
    pass

x = Foo()

print(type(x))
print(type(Foo))
<class '__main__.Foo'>
<class 'type'>

인스턴스 x의 type은 Foo인데, Foo의 type은 ‘type’이다. type에 대해 좀 더 알아보자.

for tp in int, float, dict, list, tuple:
    print(type(tp))

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

위에서 보듯이 기본 자료형들의 type은 모두 ‘type’이다. 심지어 type의 type도 type이다. 이 모든 클래스들의 원형이 되는 클래스이자 인스턴스인 녀석을 metaclass라고 부른다. metaclass의 뜻은 클래스를 만드는데 사용되는 클래스를 의미한다.

잠깐 type의 다른용도에 대해 알아보자. type은 인자를 더 사용하면, 클래스를 만들 수 있다. 메뉴얼 type항목 참조

class type(name, bases, dict)
# name : name of the class
# bases : tuple of the parent class(can be empty)
# attrs : dictionary containing attributes names and values

이는 코드상에서 ‘class’키워드를 만났을 때 하는 것과 동일하며, 다음의 두 코드는 같은일을 한다.

class MyClass():
    pass
MyClass = type("MyClass", (), {})

다시 metaclass로 돌아가 custom metaclass에 대해 알아보자.

객체를 생성하는 코드를 보면,

class Foo:
    pass

f = Foo()

Foo()를 만났을 때, Foo의 parent class의 __call__()이 불린다. super class라는걸 주의하자. Foo에서 __call__을 정의해도 불리지 않는다. 따라 올라가면, type이 나오게 되고, type에서 __call__()은 다음 두 __new__(), __init__()함수를 순서대로 호출한다. 이 두 함수는 overriding하면 그것이 호출된다.

만약 metaclass인 type을 상속받아 클래스를 만들게 되면,

class MyType(type):
    def __new__(cls, name, bases, dct):
        x = super().__new__(cls, name, bases, dct)
        x.attr = 100
        return x

metaclass를 상속받았으므로, MyType도 type의 __new__를 변형한 metaclass가 된다. 그렇다면, 이렇게 사용자가 만든 metaclass는 어떻게 사용할 수 있을까? 클래스 정의시, ‘metaclass’ 키워드를 이용한다.

class Bar(metaclass=MyType):
    pass

print(Bar.attr)
100

시작은 design pattern의 singleton 구현 때문이었는데, 자료를 찾아보는 과정에서 custom metaclass가 꼭 필요한건 아니라고 느꼈다. decorator를 이용해서 비슷한 역할이 가능하기도 하고. stack overflow의 singleton 구현 답변 참조. 어쨌든, metaclass를 이용하면 꽤 깔끔하게 구현이 되는듯.

답글 남기기 응답 취소

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

최신 글

  • Blender : snap을 써서 다른 vertex에 정렬하기
  • KTor Client 기본 사용 정리
  • 게임 만들거다.
  • Using Koin with Android Compose

보관함

2020 3월
일 월 화 수 목 금 토
1234567
891011121314
15161718192021
22232425262728
293031  
« 8월   4월 »

메타

  • 로그인
  • 엔트리 피드
  • 댓글 피드
  • WordPress.org
©2025 배토의 개발일지 | Built using WordPress and Responsive Blogily theme by Superb