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

Popular posts from this blog

html5 - What is breaking my page when printing? -

c# - must be a non-abstract type with a public parameterless constructor in redis -

ajax - PHP/JSON Login script (Twitter style) not setting sessions -