Classes already注册定义了哪些子类;打电话给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__()
is a CPython 实现细节,但该方法存在于所有支持新型类的 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
Demo:
>>> 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
Demo:
>>> 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 module如果你真的非常想效仿.__subclasses__()
行为。