473,498 Members | 1,737 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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

Hello,

I discovered this behaviour in dictionary which I find confusing. In
SneakyLang, I've tried to extend dictionary so it visits another class
after something is added:

class RegisterMap(dict):
def __setitem__(self, k, v):
dict.__setitem__(self, k,v)
self[k].visit_register_map(self)
However, when constructing dictionary with dictionary in constructor
like d = RegisterMap({'k':'v'}), __setitem__ is not called, so
workaround is needed:

class RegisterMap(dict):
def __init__(self, *args, **kwargs):
dict.__init__(self, *args, **kwargs)
for k in self:
self.__after_add(k)

def __after_add(self, k):
self[k].visit_register_map(self)

def __setitem__(self, k, v):
dict.__setitem__(self, k,v)
self.__after_add(k)
What is the reason for this behavior? Am I doing something wrong and
better approach is needed? Or should this be considered as minor bug in
Python? (tried this only in 2.4 so far)

Thank You,

Almad

Dec 12 '06 #1
8 1516
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.
Or should this be considered as minor bug in Python?
no.

</F>

Dec 12 '06 #2
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...
Dec 12 '06 #3
Mitja Trampus wrote:
I think what was unexpected for the OP is that dict.__init__
does not use __setitem__ to create its internal structures.
you can implement most methods on core objects in terms of other
methods. picking one by random, and then complaining that other
methods don't use the one you picked, strikes me as a rather
naive view of how object-oriented design works in practice.

</F>

Dec 12 '06 #4
Mitja Trampus wrote:

....
At least, I know it surprised me when I first met this behavior. Or is
my reasoning incorrect?
Why len() doesn't call iteritems() ? :-)

Kidding apart for example it would be ok for __setitem__
to call either an internal "insert_new_item" or
"update_existing_item" depending on if the key is
already present in the dictionary.
In this case I suppose you agree it would make a lot
of sense to go directly for "insert_new_item" in the
constructor from a dict instead of calling the public
__setitem__...

The key point is that you're not authorized to assume
constructing a dictionary from a dictionary will use
__setitem__ unless this is explicitly stated in the
interface.

....
What I find an even nastier surprise is that dict.update behaves this
way as well:
....
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]
I cannot understand this doc string at all.

The explanation in the manual however just talks about
"updating", with no reference to assignments. The manual
of 2.3 instead was using a code example and I'd say this
would qualify as a binding to actually implement calls
to __setitem__. This kind of error (i.e. over-specifying
by providing actual code that implies specific side-effects)
was also present in the C++ standard, and in at least
one case an implementation would have to be very
inefficient to comply on the issue (this fortunately is
not what happened, the standard was "fixed" instead).

If there is a bug in this case is IMO a docstring bug.

Andrea
Dec 13 '06 #5

"Almad" <bu**@almad.netwrote in message
news:11*********************@j72g2000cwa.googlegro ups.com...
Hello,

I discovered this behaviour in dictionary which I find confusing
....
However, when constructing dictionary with dictionary in constructor
like d = RegisterMap({'k':'v'}), __setitem__ is not called,
d.__setitem__(k,v) is the internal translation of d[k] = v (when such is
explicitly written in this code). d.__init__(otherdict) need not go thru
that interface if a more direct means is available.
>so workaround is needed:
Your 'workaround' seems to be the proper solution.
Am I doing something wrong
Denigrating a solution because it does not meet your expectation.

Your are not the first to do this ;-).

tjr


Dec 13 '06 #6
[Almad]
I discovered this behaviour in dictionary which I find confusing. In
SneakyLang, I've tried to extend dictionary so it visits another class
after something is added:

class RegisterMap(dict):
def __setitem__(self, k, v):
dict.__setitem__(self, k,v)
self[k].visit_register_map(self)
However, when constructing dictionary with dictionary in constructor
like d = RegisterMap({'k':'v'}), __setitem__ is not called,
Try subclassing from UserDict.DictMixin.
Raymond

Dec 13 '06 #7
Thanks to everybody for replies, I'm now satisfied ^_^

Almad

Dec 14 '06 #8
Final note: one of the developers ran into a similar issue with dict and
has opened a discussion on pydev about how the C implementation might be
changed to have derived classes act more consistently without imposing a
time penalty on the normal use of dict. There might possibly be a change
by 2.6 but I am not following the details.

tjr

Dec 14 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
2404
by: ±è»ó¿Ï | last post by:
I'm a newbie in Python and Python/C API.. I have a simple question. I want to access python dictionary data type from C extension module. ---- spam.c ---- #include <Python.h> PyObject...
125
7064
by: Raymond Hettinger | last post by:
I would like to get everyone's thoughts on two new dictionary methods: def count(self, value, qty=1): try: self += qty except KeyError: self = qty def appendlist(self, key, *values): try:
2
1963
by: Alex | last post by:
Entering >>> help(dict) Help on class dict in module __builtin__: class dict(object) | dict() -> new empty dictionary. | dict(mapping) -> new dictionary initialized from a mapping object's...
1
2683
by: Crutcher | last post by:
I've been playing with dictionary subtypes for custom environments, and I encountered a strange interaction between exec, dictionary subtypes, and global variables. I've attached a test program,...
8
7029
by: rh0dium | last post by:
Hi all, I have a dict which looks like this.. dict={'130nm': {'umc': }, '180nm': {'chartered': , 'tsmc': }, '250nm': {'umc': , 'tsmc': } }
2
3552
by: Tom Grove | last post by:
I have a server program that I am writing an interface to and it returns data in a perl dictionary. Is there a nice way to convert this to something useful in Python? Here is some sample data:...
3
1595
by: craigkenisston | last post by:
I want to use Dictionary class like this: textboxM.Text = oMyDict.GetValue("textboxM"); textboxN.Text = oMyDict.GetValue("textboxN"); Where my dictionary contains the list of values for my...
8
2106
by: james_027 | last post by:
hi for example I have this dictionary dict = {'name':'james', 'language':'english'} value = 'sex' in dict and dict or 'unknown' is a right pythonic of doing this one? I am trying to get a...
11
1819
by: not_a_commie | last post by:
given a Dictionary<object, objectand an object that exactly replicates the Equals and GetHashCode of the original object used as the dictionary key, how do I retrieve the original key that was used?
0
7125
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7002
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
1
6887
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
5462
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4910
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4590
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3093
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3085
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
291
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.