2013-04-05 2 views
3

필자는 Python을 오랫동안 사용 해왔고, 나는 항상 메타 클래스의 의미를 다소 이해해 왔지만 필자는 절대로 필요하지 않았습니다. 이제는 내 문제에 대한 최상의 솔루션이 메타 클래스라고 생각합니다.간단한 메타 클래스는 어떻게 만듭니 까?

내가 만들고자하는 것은 클래스 변수 n과 목록 instances을 각 클래스에 자동으로 추가하는 시스템입니다.

class Foo: 
    n = 0 
    instances = [] 

    def __init__(self): 
     self.index = Foo.n 
     Foo.n += 1 
     Foo.instances.append(self) 

이 구조 내 7 개 또는 8 클래스를 구현해야하고, 나는 메타 클래스가 나를 여기에 도움이 될 것으로 생각했다 : 여기에 하나 개의 클래스의 간단한 예입니다. Foo.__metaclass__ = MyMetaclass 특성을 사용할 수 있다는 것을 알고 있습니다. 메타 클래스를 만드는 방법은 무엇입니까?

답변

1

사실, 기본 클래스를 사용하여 여기에 더 나은 운동 것 :

class InstancesList(object): 
    def __new__(cls, *args, **kw): 
     if not hasattr(cls, 'instances'): 
      cls.instances = [] 
     return super(InstancesList, cls).__new__(cls, *args, **kw) 

    def __init__(self): 
     self.index = len(type(self).instances) 
     type(self).instances.append(self) 

class Foo(InstancesList): 
    def __init__(self, arg1, arg2): 
     super(Foo, self).__init__() 
     # Foo-specific initialization 
+0

@ MarkusMeskanen : 예, 실제로 마음이 바뀌었고 대신 기본 클래스를 제공하고 있습니다. 메타 클래스는 잔인하며 결국 원하는 것을 제공하지 않습니다. 메타 클래스는 대신 클래스 당 인스턴스 사전을 보관해야합니다. –

+0

아무도 다른 사람이 더 나은 해결책을 제공 할 수 없다면 나는 이것을 사용할 것입니다. 답변 해주셔서 감사합니다 :) –

1

는 메타 클래스를 사용하는 방법을 배울 것을 두려워하지 마십시오.

#!/usr/bin/env python3 

def main(): 
    x = Foo() 
    print('x.index:', x.index) 
    print('x.n:', x.n) 
    print('x.instances:', x.instances) 
    print('x.instances[0] == x:', x.instances[0] == x) 

class MyMetaClass(type): 

    def __new__(cls, name, bases, namespace): 
     namespace.setdefault('n', 0) 
     namespace.setdefault('instances', []) 
     namespace.setdefault('__new__', cls.__new) 
     return super().__new__(cls, name, bases, namespace) 

    @staticmethod 
    def __new(cls, *args): 
     instance = cls.__base__.__new__(cls) 
     instance.index = cls.n 
     cls.n += 1 
     cls.instances.append(instance) 
     return instance 

class Foo(metaclass=MyMetaClass): 

    def __init__(self): 
     print('Foo instance created') 

if __name__ == '__main__': 
    main()