我希望通过让每个子类在父类保存的列表中注册自己来制作给定类的所有子类的列表,即像这样:

class Monster(object):
    monsters = list()
class Lochness(Monster):
    Monster.monsters.append(Lochness)
class Yeti(Monster):
    Monster.monsters.append(Yeti)

这显然不起作用,因为当我想将它们添加到列表时还没有创建类。而且,如果它是自动完成的会更好(比如 __subclass__)

我知道 __subclass__ 有这个功能,但我想知道(为了我自己的启发)你如何自己实现它。

似乎您想要创建元类的某种子类,该子类正在创建所有内容以将其注册到 Monster?或者是完全偏离基地

最佳答案

类已经注册了定义的子类;调用 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 ,但该方法存在于所有支持新式类的 Python 版本(2.2 及更高版本,一直到 3.x)中。

否则, Hook 类创建的规范方法是定义 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 类型,或使用显式装饰器。

无论哪种方式,元类或类装饰器都会注册一个永久引用。如果您真的非常想模拟 weakref 行为,则可以使用 .__subclasses__() module

关于python - 构造类对象后执行代码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17784398/

10-12 17:01