2012-06-07 21 views
12

Yo estaba jugando con metaclases en CPython 3.2.2, y me di cuenta que es posible terminar con una clase que es su propio tipo:Python: ¿un objeto puede ser de su propio tipo?

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 

Para nuestro metaclase A, hay en realidad no parecen a ser mucho de una distinción entre clase y la instancia atributos:

>>> 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__` 

Todo esto funciona de la misma (aparte de cambiar a __metaclass__ y __next__ no ser un método especial) en CPython 2.7.2, 1.6.0 PyPy (que implementa Python 2.7.1) y Jython 2.2.1 (no tiene idea de qué Python versión que es, si hay alguna - No estoy muy familiarizado con Jython).

No puedo encontrar muchas explicaciones sobre las condiciones bajo las cuales se permite la asignación a __class__ (aparentemente los tipos en cuestión deben ser definidos por el usuario y tienen un diseño similar en algún sentido?). Tenga en cuenta que A tiene que ser tanto una subclase como una instancia de MC para que funcione la asignación a __class__. ¿Se supone que las jerarquías de metaclass recursivas como esto son aceptables? Estoy muy confundido.

+1

Un documento que explica mucho sobre los tipos de Python es el siguiente: http://www.cafepy.com/article/python_types_and_objects/python_types_and_objects.html Debe aclarar las cosas, aunque no parece discutir esta situación. –

Respuesta

6

jerarquías MetaClass recursivos son en realidad parte del núcleo idioma:

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

Así que incluso la metaclase estándar type es su propio tipo. No hay ningún problema conceptual con esta construcción; solo significa que el atributo __class__ de la clase apunta a la clase misma.

Las asignaciones al atributo __class__ solo se permiten para las clases definidas por el usuario. La asignación es legal si la clase original y la nueva clase no definen __slots__, o ambos establecen __slots__ en la misma secuencia.

Cuestiones relacionadas