12

I was playing around with metaclasses in CPython 3.2.2, and I noticed it is possible to end up with a class that is its own type:

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

For our metaclass A, there doesn't really seem to be much of a distinction between class and instance attributes:

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

All this works the same (apart from changing to __metaclass__, and __next__ not being a special method) in CPython 2.7.2, PyPy 1.6.0 (which implements Python 2.7.1), and Jython 2.2.1 (no idea what Python version that is, if any - I'm not very familiar with Jython).

I can't find much explanation about the conditions under which assigning to __class__ is allowed (apparently the types concerned must be user-defined and have a similar layout in some sense?). Note that A does have to be both a subclass and an instance of MC for the assignment to __class__ to work. Are recursive metaclass hierarchies like this really supposed to be acceptable? I'm very confused.

4

1 回答 1

6

递归元类层次结构实际上是语言核心的一部分:

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

所以即使是标准的元类type也是它自己的类型。这个构造没有概念上的问题——它只是意味着类的__class__属性指向类本身。

__class__只有用户定义的类才允许对属性进行分配。如果原始类和新类都没有定义__slots__,或者都设置__slots__为相同的序列,则分配是合法的。

于 2012-06-07T21:01:28.567 回答