Python新式类和__subclasses__函数

时间:2010-05-20 19:28:30

标签: python

有人可以向我解释为什么会这样(在Python 2.5中):

class Foo(object):
    pass

class Bar(Foo):
    pass

print(Foo.__subclasses__())

但这不是:

class Foo():
    pass

class Bar(Foo):
    pass

print(Foo.__subclasses__())

后者返回“AttributeError:class Foo没有属性'__subclasses__'”,但我不确定原因。我知道这与旧式和新式类有关,但我不清楚为什么会使这个功能不可用。

澄清:我希望了解为什么__subclasses__()在旧式中不可用,我知道这种方法对于旧式课程不存在但我不知道得到新风格的东西使这些新功能成为可能。

2 个答案:

答案 0 :(得分:30)

class Foo(object):
    pass

上面的类是“新风格”类,因为它继承自对象类。新式类提供了许多“旧式”类没有的额外框架。新样式类的一个特定属性是能够使用 __ subclasses __ 方法确定类的子类。

关于新式类的some good discussion和完全undocumented __ subslasses __ 方法。 (Here是Tim Peters的非正式解释。)

“每个新样式类都保留一个对其直接子类的弱引用列表。此方法返回所有那些仍处于活动状态的引用的列表。”

所以为了回答你的问题, __ subslasses __ 功能不可用,因为在你的第二个例子中:

class Foo():
    pass

旧式类Foo不继承自对象(因此它不是新式类),并且没有继承 __ subslasses __ 方法。

注意,如果您不理解为什么旧式类没有 __ subclasses __ 方法,您可以随时启动python解释器并使用 dir

>>> class Foo(object):
...     pass
...
>>> dir(Foo.__class__)
['__abstractmethods__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__delattr__', '__dict__', '__dictoffset__', '__doc__', '__
eq__', '__flags__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__instancecheck__', '__itemsize__', '__le__', '__lt
__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__s
ubclasscheck__', '__subclasses__', '__subclasshook__', '__weakrefoffset__', 'mro']
>>> class Bar():
...     pass
...
>>> dir(Bar.__class__)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: class Bar has no attribute '__class__'
>>> dir(Bar)
['__doc__', '__module__']
>>> dir(Foo)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '
__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

答案 1 :(得分:3)

添加上面的答案。

Python 3.0有一个单独的类实现。 Subclassing是Python 3.0中的一个特性,而不是Python 2.0。

因此,如果您安装python 3.x并执行

class Foo():
    pass

class Bar(Foo):
    pass

print(Foo.__subclasses__())

它不会给出任何属性错误。

现在,通过在每个类定义中继承“object”基类,相同的功能扩展到Python 2.0类。

所以如果你用Python 2.x:

class Foo(object):
    pass

class Bar(Foo):
    pass

print(Foo.__subclasses__())

由于您在新类Foo中继承 object 基类,因此继承了3.x样式类,并且没有出现属性错误。

但是当你在Python 2.x中做的时候

class Foo():
    pass

class Bar(Foo):
    pass

print(Foo.__subclasses__())

这意味着,新样式类尚未被继承,并且由于子类是新样式类的一部分,因此会抛出属性错误。

请记住,如果要将任何Python 3.x类功能扩展到Python 2.x,则需要在类定义中继承 object 类。

希望这会有所帮助。