I need a collection of objects which can be looked up by a certain (unique) attribute common to each of the objects. Right now I am using a dicitionary assigning the dictionary key to the attribute.
Here is an example of what I have now:
class Item():
def __init__(self, uniq_key, title=None):
self.key = uniq_key
self.title = title
item_instance_1 = Item("unique_key1", title="foo")
item_instance_2 = Item("unique_key3", title="foo")
item_instance_3 = Item("unique_key2", title="foo")
item_collection = {
item_instance_1.key: item_instance_1,
item_instance_2.key: item_instance_2,
item_instance_3.key: item_instance_3
}
item_instance_1.key = "new_key"
Now this seems a rather cumbersome solution, as the key is not a reference to the attribute but takes the value of the key-attribute on assignment, meaning that:
- the keys of the dictionary duplicate information already present in form of the object attribute and
- when the object attribute is changed the dictionary key is not updated.
Using a list and iterating through the object seems even more inefficient.
So, is there more fitting data structure than dict for this particular case, a collection of objects giving me random access based on a certain object attribute?
This would need to work with Python 2.4 as that’s what I am stuck with (at work).
If it hasn’t been obvious, I’m new to Python.
There is actually no duplication of information as you fear: the dict’s key, and the object’s
.keyattribute, are just two references to exactly the same object.The only real problem is “what if the
.keygets reassigned”. Well then, clearly you must use a property that updates all the relevant dicts as well as the instance’s attribute; so each object must know all the dicts in which it may be enregistered. Ideally one would want to use weak references for the purpose, to avoid circular dependencies, but, alas, you can’t take aweakref.ref(or proxy) to a dict. So, I’m using normal references here, instead (the alternative is not to usedictinstances but e.g. some special subclass — not handy).Edit: if you want a single collection with ALL the instances of Item, that’s even easier, as you can make the collection a class-level attribute; indeed it can be a WeakValueDictionary to avoid erroneously keeping items alive, if that’s what you need. I.e.:
Now you can use
Item.all['akey'],Item.all.get('akey'),for akey in Item.all:, and so forth — all the rich functionality of dicts.