2012-06-07 7 views
12

Ich war mit metaclasses in CPython 3.2.2 herum spielen, und ich bemerkte, dass es möglich ist, mit einer Klasse am Ende, das seine eigene Art ist:Python - ein Objekt kann ein eigener Typ sein?

Python 3.2.2 (default, Sep 5 2011, 21:17:14) 
[GCC 4.6.1] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> class MC(type):   #a boring metaclass that works the same as type 
...  pass 
... 
>>> class A(MC, metaclass=MC): #A is now both a subclass and an instance of MC... 
...  pass 
... 
>>> A.__class__ = A   #...and now A is an instance of itself? 
>>> A is type(A) 
True 

Für unsere metaclass A, ist es nicht wirklich scheint viel von einer Unterscheidung zwischen Klasse und der Instanz seinem Attribut:

>>> A.__next__ = lambda self: 1 
>>> next(A) 
1          #special method lookup works correctly 
>>> A.__dict__ 
dict_proxy({'__module__': '__main__', 
'__next__': <function <lambda> at 0x17c9628>, 
'__doc__': None}) 
>>> type(A).__dict__ 
dict_proxy({'__module__': '__main__', 
'__next__': <function <lambda> at 0x17c9628>, 
'__doc__': None})        #they have the same `__dict__` 

dies das gleiche arbeitet All (abgesehen von __metaclass__ Ändern und __next__ eine spezielle Methode nicht ist) in CPython 2.7.2, 1.6.0 PyPy (welche Python 2.7.1) und Jython 2.2.1 implementiert (keine Ahnung was Python Version, die, wenn überhaupt - ich bin nicht sehr vertraut mit Jython).

Ich kann nicht viel Erklärung über die Bedingungen finden, unter denen die Zuordnung zu __class__ erlaubt ist (anscheinend müssen die betroffenen Typen benutzerdefiniert sein und haben ein ähnliches Layout in einem gewissen Sinne?). Beachten Sie, dass A sowohl eine Unterklasse als auch eine Instanz von MC für die Zuweisung zu __class__ sein muss. Sind rekursive Metaklassenhierarchien wie diese eigentlich akzeptabel? Ich bin sehr verwirrt.

+1

Ein Dokument, das viel über Python-Typen erklärt, ist das Folgende: http://www.cafepy.com/article/python_types_and_objects/python_types_and_objects.html Es sollte die Dinge klären, obwohl es scheint, diese Situation nicht zu diskutieren. –

Antwort

6

rekursive metaclass Hierarchien sind tatsächlich Teil der Sprachkern:

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

So auch die Standard-Metaklasse type ist seine eigene Art. Es gibt kein konzeptionelles Problem mit diesem Konstrukt - es bedeutet nur das __class__ Attribut der Klasse zeigt auf die Klasse selbst.

Zuweisungen zum Attribut __class__ sind nur für benutzerdefinierte Klassen zulässig. Die Zuweisung ist zulässig, wenn entweder die ursprüngliche Klasse und die neue Klasse __slots__ nicht definieren oder beide __slots__ auf dieselbe Sequenz setzen.