类已经注册了定义的子类;调用class.__subclasses__()
方法获取列表:
>>> class Monster(object):
... pass
...
>>> class Lochness(Monster):
... pass
...
>>> class Yeti(Monster):
... pass
...
>>> Monster.__subclasses__()
[<class '__main__.Lochness'>, <class '__main__.Yeti'>]
.__subclasses__()
返回当前仍然存在的子类的列表。如果您曾经清除对Yeti
(del Yeti
在模块中,删除所有实例、子类、导入等) 的所有引用,那么当您调用.__subclasses__()
. 请注意,本质上,.__subclasses__()
是一个CPython implementation detail,但该方法存在于所有支持新样式类的 Python 版本中(2.2 及更高版本,一直到 3.x)。
否则,挂钩类创建的规范方法是定义一个元类:
class MonstersMeta(type):
def __new__(metaclass, name, bases, namespace):
cls = super(MonstersMeta, metaclass).__new__(metaclass, name, bases, namespace)
if issubclass(cls, Monster) and not cls is Monster:
Monster.monsters.append(cls)
return cls
class Monster(object):
__metaclass__ = MonstersMeta
monsters = []
class Lochness(Monster):
pass
class Yeti(Monster):
pass
演示:
>>> class Monster(object):
... __metaclass__ = MonstersMeta
... monsters = []
...
>>> class Lochness(Monster):
... pass
...
>>> class Yeti(Monster):
... pass
...
>>> Monster.monsters
[<class '__main__.Lochness'>, <class '__main__.Yeti'>]
或者您可以使用类装饰器:
def registered_monster(cls):
Monster.monsters.append(cls)
return cls
class Monster(object):
monsters = []
@registered_monster
class Lochness(Monster):
pass
@registered_monster
class Yeti(Monster):
pass
演示:
>>> class Monster(object):
... monsters = []
...
>>> @registered_monster
... class Lochness(Monster):
... pass
...
>>> @registered_monster
... class Yeti(Monster):
... pass
...
>>> Monster.monsters
[<class '__main__.Lochness'>, <class '__main__.Yeti'>]
不同之处在于您将注册怪物的责任放在哪里;使用基本MonstersMeta
类型,或使用显式装饰器。
无论哪种方式,元类或类装饰器都会注册一个永久引用。如果您真的非常想模仿这种行为,您可以使用该weakref
模块。.__subclasses__()