On 17 sep, 19:10, <[EMAIL PROTECTED]> wrote: > I'd like some advices from more experienced python users. I want to > have a class in my python application that does not allow multiple > instance with same "name". > > I want to have a class (call it kls) that behave at least following way: > > 1) New instance has to have a property called 'name' > 2) When instance is attemped to created, e.g., x=kls(name='myname'), and > there already exists an instance with obj.name =='myname', that > pre-existing instance is returned, instead of making new one.
For all of this I would use the __new__ method. > 3) A class property 'all' for class gives me a list of all the > instances. So kls.all lets me iterates through all instances. > 4) When all the hard-link to an instance is deleted, the instance should > be deleted, just like an instance from any regular class does. I'd store a WeakValueDictionary using the name as a key. Instead of a property 'all', I'd use a method 'get_all_instances()' that should call values() on the weak dictionary. > My question is if i can find metaclass or something that allows me to > create such class easily. I tried to search such thing on internet, but > I even don't know how to call this kind of thing. It is in a sense like > singleton, but less restrictive. Have you tried the Python Cookbook? > Assuming that I have to write it on my own, what should I do? I tried > to implement it using weakref.WeakValueDictionary and metaclass, but > instance doesn't disappear when I think it should disappear. I am also > wondering if it is easier to keeping {name:id(obj)} would be a better > solution. A WeakValueDictionary should work. If the instance is not deleted when you expect, maybe there are other references somewhere, or the garbage collector didn't run yet. Ok, finally I wrote an example: py> from weakref import WeakValueDictionary py> py> class OneOfAKind(object): ... _instances = WeakValueDictionary() ... def __new__(cls, name): ... inst = cls._instances.get(name, None) ... if inst is None: ... inst = cls._instances[name] = super(OneOfAKind, cls).__new__(cls ) ... inst.name = name ... return inst ... @classmethod ... def get_all_instances(cls): ... return cls._instances.values() ... __str__ = __repr__ = lambda self: '%s(%r)' % (self.__class__.__name__, s elf.name) ... py> a = OneOfAKind('A') py> b = OneOfAKind('A') py> assert b is a py> c = OneOfAKind('C') py> assert c is not a py> print OneOfAKind.get_all_instances() [OneOfAKind('A'), OneOfAKind('C')] py> del c py> import gc py> gc.collect() 17 py> print OneOfAKind.get_all_instances() [OneOfAKind('A')] py> del a py> del b py> gc.collect() 0 py> print OneOfAKind.get_all_instances() [] py> -- Gabriel Genellina -- http://mail.python.org/mailman/listinfo/python-list