python - Executing code after construction of class object -
i hoping make list of subclasses of given class having each subclass register in list parent class holds, ie this:
class monster(object): monsters = list() class lochness(monster): monster.monsters.append(lochness) class yeti(monster): monster.monsters.append(yeti)
this doesn't work because classes haven't been created yet when want add them list. and, it'd nicer if done automatically (like __subclass__)
i'm aware __subclass__ has functionality, wondering (for own edification) how you'd implement yourself.
it seems you'd want create sort of subclass of metaclass creating register monster? or off base
classes already register subclasses defined; call class.__subclasses__()
method list:
>>> class monster(object): ... pass ... >>> class lochness(monster): ... pass ... >>> class yeti(monster): ... pass ... >>> monster.__subclasses__() [<class '__main__.lochness'>, <class '__main__.yeti'>]
.__subclasses__()
returns list of currently still alive subclasses. if ever clear references yeti
(del yeti
in module, delete instances, subclasses, imports, etc.) it'd no longer listed when call .__subclasses__()
. note in essence, .__subclasses__()
cpython implementation detail, method present in python versions support new-style classes (2.2 , up, way 3.x).
otherwise, canonical way hook class creation define metaclass:
class monstersmeta(type): def __new__(metaclass, name, bases, namespace): cls = super(monstersmeta, metaclass).__new__(metaclass, name, bases, namespace) if issubclass(cls, monster) , not cls 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'>]
or can use 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
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'>]
the difference being put responsibility of registering monsters; base monstersmeta
type, or explicit decorators.
either way, metaclass or class decorator registers permanent reference. can use weakref
module if really, want emulate .__subclasses__()
behaviour.
Comments
Post a Comment