Hey guys, author of addict here. Would appreciate immensely if you would file issues of problems you find. It's a very new project, that I cooked up after work hours this week, and any input is good input! Thanks.
This uses twice as much memory as it needs to (and opens the door to potential inconsistency) by storing everything redundantly in both the attributes dictionary and the underlying dict.
Setting an item with a non-string key (e.g. An int or even unicode) is silently ignored.
myDict[u'foo'] = 'bar' # <- this ought to do something
Setting or deleting an item with the same name as an existing attribute (e.g. the name of a method) will replace or delete that attribute. myDict['get'] = 'foo' # <- should not replace the method myDict.get
This can't be initialised with kwargs or an iterator like an ordinary dict can.The mutate-on-get makes it very similar to how Matlab does its "structs", I'm mostly undecided on that but at times it can be nice.
Suppose I have an empty defaultdict(list). I do the following:
d = defaultdict(list)
l = d['foo']
According to no-mutate-on-get semantics, we now have an empty list, and d is still empty.
So what happens if I do: l.append('bar')
You might expect the dict to now be populated with {'foo': ['bar']}. However, the dict has no way of knowing (without a large amount of additional tricks) whether the new list that it previously returned had been later modified. So what would actually happen would be nothing, d would remain empty. Worse, now your behaviour is different depending on whether or not the 'foo' key was already present (if it was, you would've gotten a reference to the actual value and mutated it, and d would have changed as a result).As I see it, there are only two sane solutions to this problem: Either immediately store every generated value so any subsequent mutation is saved (the solution used here)...or require that your default values be immutable.