d = {}; d[0:1] = 1; d[0:1] = 2; print d[:]

Donn Cave donn at oz.net
Thu Mar 1 01:06:51 EST 2001


Quoth Robin Thomas <robin.thomas at starmedia.net>:
| Using Python 2.0 on Win32. Am I the only person to be depressed by the 
| following behavior now that __getitem__ does the work of __getslice__?
|
| Python 2.0 (#8, Oct 16 2000, 17:27:58) [MSC 32 bit (Intel)] on win32
|  >>> d = {}
|  >>> d[0:1] = 1
|  >>> d
| {slice(0, 1, None): 1}
|
| And then, for more depression:
|
|  >>> d[0:1] = 2
|  >>> d
| {slice(0, 1, None): 1, slice(0, 1, None): 2}
|
| And then, for extra extra chagrin:
|
|  >>> print d[0:1]
| Traceback (innermost last):
|    File "<pyshell#11>", line 1, in ?
|      d[0:1]
| KeyError: slice(0, 1, None)

If it helps, you ruined my day.

| So, questions:
|
| 1) Is this behavior considered a bug by the BDFL or the community at large? 
| If so, has a fix been conceived? Am I re-opening a long-resolved issue?
|
| 2) If we're still open to proposed solutions, which of the following do you 
| like:
|
|     a) make slices hash and cmp as their 3-tuple (start,stop,step),
|        so that if I accidentally set a slice object as a key,
|        I can at least re-set it or get it or del it :)
|
|     b) have dict.__setitem__ expressly reject objects of SliceType
|        as keys, raising your favorite in (TypeError, ValueError)

I think we might be able to do better.  I hacked in a quick fix
in ceval.c that looks to me like it has the desired effect without
closing the door to intentional slice keys (however unlikely.)

    Python 2.1a2 (#1, Feb 28 2001, 21:53:26)
    [GCC egcs-2.91.66 19990314 (egcs-1.1.2 release)] on netbsd1
    Type "copyright", "credits" or "license" for more information.
    >>> d = {}
    >>> d[1:4] = 7
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    TypeError: dict object doesn't support slice assignment
    >>> f = slice(1, 4, None)
    >>> d[f] = 7
    >>> 

The change:
*** Python/ceval.c.dist Thu Feb  1 14:48:12 2001
--- Python/ceval.c      Wed Feb 28 21:52:55 2001
***************
*** 3168,3173 ****
--- 3168,3178 ----
        /* u[v:w] = x */
  {
        int ilow = 0, ihigh = INT_MAX;
+       if (u->ob_type->tp_as_mapping) {
+               PyErr_SetString(PyExc_TypeError,
+                       "dict object doesn't support slice assignment");
+               return -1;
+       }
        if (!_PyEval_SliceIndex(v, &ilow))
                return -1;
        if (!_PyEval_SliceIndex(w, &ihigh))

-End patch.

I don't know if this is the answer, but it at least demonstrates
that [:] and slice() can be separate issues at some level.

	Donn Cave, donn at oz.net



More information about the Python-list mailing list