类已经注册定义了哪些子类;拨打class.__subclasses__() method获取列表:
>>> 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,但该方法存在于所有支持新型类(2.2 及更高版本,一直到 3.x)的 Python 版本中。
否则,挂钩到类创建的规范方法是定义一个metaclass:
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'>]
或者你可以使用class decorator:
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 类型,或使用显式装饰器。
无论哪种方式,元类或类装饰器都会注册一个永久引用。如果您真的非常想模仿.__subclasses__() 的行为,可以使用weakref module。