상세 컨텐츠

본문 제목

Metaclass

Python

by techbard 2016. 5. 3. 12:58

본문

반응형

# 같은 형태의 클래스를 여러개 사용할때 효과적으로 생성


class AttributeInitType(type):

def __call__(self, *args, **kwargs):

obj = type.__call__(self, *args)

for name, value in kwargs.items():

setattr(obj, name, value)

return obj


class Submarine(object, metaclass = AttributeInitType):

# attrs = ['color', 'year', 'name']

  pass


sub = Submarine(name = 'Narwal', year = 2000, color = 'Black')


print(sub.year)


# 결과

2000


# 상속으로는 부모 클래스의 __init__이 실행되지 않는다.


class Meta():

def __init__(self, name, bases, namespace):

self.val = 10


class Ma(Meta):

pass


print(Ma.val)


# 결과

AttributeError: type object 'Ma' has no attribute 'val'



# metaclass로는 __init__이 실행된다.

class Meta(type):

def __init__(self, *args):

self.val = 10


class Ma(metaclass=Meta):

pass


print(Ma.val)

print(Ma().val)


# 결과

10

10


# 상속과는 달리 metaclass를 이용해 만들어진 객체 참조로는 자기 자신의 메쏘드만 접근 가능하다.


class Meta(type):

def go(self):

return "go"


class Ma(metaclass=Meta):

def ma(self):

return "Ma"


m1 = Ma()

print(m1.ma())


# 결과

Ma


m1 = Ma()

print(m1.go())


# 결과

AttributeError: 'Ma' object has no attribute 'go'


"""

metaclass를 사용하는 목적이 동적으로 객체 생성을 하기 위함이므로

metaclass 자체는 __init__을 실행할 필요가 없다.

따라서, 초기화가 아닌 객체 생성만 목적으로 하면 __new__만 사용한다.

"""


class Meta(type):

def __new__(self, *a):

self.val = 10 # do something

return type.__new__(self, *a)


class Ma(metaclass=Meta):

pass


m1 = Ma # 인스턴스를 만들 수 없고 메타 클래스의 인스턴스만 가르킨다.

print(m1.val)


# 결과

10


m1.val = 20 # 생성된 객체를 리턴하기 때문에 인자 전달도 가능하다.

print(m1.val)


# 결과

20


반응형

관련글 더보기

댓글 영역