[Python-Dev] Mundane dict __setitem__...
David Abrahams
dave@boost-consulting.com
Tue, 03 Jun 2003 12:15:06 -0400
"Tim Peters" <tim@zope.com> writes:
> [David Abrahams]
>>> I am about to write some code which relies on the following:
>>>
>>> x = (1,2,3)
>>> y = (1,2,3)
>>> d = {}
>>> d[x] = 1
>>> d[y] = 1
>>> assert d.keys()[0] is y
>>>
>>> In other words, when you do d[k] = v it replaces both v *and* k in
>>> the dict. I couldn't find it documented anywhere but the source. I
>>> submitted a doc patch which enshrines that behavior, but since Guido
>>> doesn't always know what's in the doc I wanted to make sure it was
>>> considered reasonable.
>>>
>>> Anyone want to tell me it's a bad idea? It seems like the more
>>> useful of the two possible behaviors to me.
>
> [Samuele Pedroni]
>> that's not the case with Jython, i.e. the assert will fail in Jython.
>
> It probably fails in CPython too:
>
>>>> x = (1, 2, 3)
>>>> y = (1, 2, 3)
>>>> d = {x: 1}
>>>> d[y] = 1
>>>> map(id, d.keys()) # shows that x is still a key
> [7872560]
>>>> id(x), id(y)
> (7872560, 8348336)
>>>>
>
> Dave, what made you think x gets replaced?
The source, Luke. But sadly I was just mis-reading the wrong branch
of the if clause. It's hard to understand why that Py_DECREF is
needed, but it was just the distraction my hopeful brain needed to
tell me it would work ;-(
static void
insertdict(register dictobject *mp, PyObject *key, long hash, PyObject *value)
{
PyObject *old_value;
register dictentry *ep;
typedef PyDictEntry *(*lookupfunc)(PyDictObject *, PyObject *, long);
assert(mp->ma_lookup != NULL);
ep = mp->ma_lookup(mp, key, hash);
if (ep->me_value != NULL) {
old_value = ep->me_value;
ep->me_value = value;
Py_DECREF(old_value); /* which **CAN** re-enter */
Py_DECREF(key);
}
else {
if (ep->me_key == NULL)
mp->ma_fill++;
else
Py_DECREF(ep->me_key);
^^^^^^^^^^^^^^^^^^^^^
ep->me_key = key;
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com