Inconsistency in dictionary behaviour: dict(dict) not calling __setitem__

Mitja Trampus nun at example.com
Tue Dec 12 17:33:41 EST 2006


Fredrik Lundh wrote:
> Almad wrote:
> 
>> However, when constructing dictionary with dictionary in constructor
>> like d = RegisterMap({'k':'v'}), __setitem__ is not called
> 
> why should it do that?  dict() is a concrete implementation, not a 
> template class for the creation of dict-like objects.

I think what was unexpected for the OP is that dict.__init__ 
does not use __setitem__ to create its internal structures. 
This is independent of dict being a concrete implementation 
or not:

 >>> class H:
...  def __init__(self): self.hello()
...  def hello(self): print 'oi oi'
 >>> class K(H):
...  def hello(self): print 'hello'
 >>> K()
hello
<__main__.K instance at 0x00AC9878>

At least, I know it surprised me when I first met this 
behavior. Or is my reasoning incorrect?

Further to the OP: This is due to optimizations - 
initialization is much faster if it's done by modifying 
dict's internal state directly and thus without calling a 
(possibly custom-made) method for each item to be inserted.
What I find an even nastier surprise is that dict.update 
behaves this way as well:

 >>> class D(dict):
...  def __setitem__(self,k,v):
...   print 'setting',k,'to',v
...   dict.__setitem__(self,k,v)
 >>> d=D({1:'a', 2:int})
# No output here - OK, half-expected
 >>> d.update({3:'s',6:23})
# No output here, either...

The docstring is, at best, misguiding on this particular point:

 >>> print d.update.__doc__
D.update(E, **F) -> None.  Update D from E and F: for k in 
E: D[k] = E[k]
(if E has keys else: for (k, v) in E: D[k] = v) then: for k 
in F: D[k] = F[k]


It's not a big issue, but an almost sure one-time surprise 
for everyone, I suppose...



More information about the Python-list mailing list