range(Instance) vs. foo[Instance]

Michael P. Reilly arcege at shore.net
Fri Jul 9 09:08:02 EDT 1999


Jeff Epler <jepler at inetnebr.com> wrote:
: Suppose I have a class with __int__ defined:

: class c:
:   def __init__(self, val):
:     self.val = int(val)

:   def __int__(self): return self.val

:>>> x=c(1)
:>>> range(x)
: [0]
:>>> (0,1,2)[x]
: Traceback (innermost last):
:   File "<stdin>", line 1, in ?
: TypeError: sequence index must be integer

: It seems desirable that the subscript operator call x.__int__ just like
: range() must effectively do.  Is there some reason why not?

: (Not the subscript operator in general, but the subscript operator for
: the builtin types of lists and tuples)

: I ask because I recently wrote a 5-minute hack on top of bytecodehacks that
: makes "integers" function as rational numbers in the interactive Python
: console---functions like "range" work, but subscripting of tuples and lists
: is broken.

: Jeff

Yup, this sounds like a bug, since [].insert( c(0), "spam") would work
as you expect.  Some reasons to not have this would be:
* How do you handle complex numbers as subscripts,
* Strings containing numbers as subscripts.

But this looks like a holdover from older code.  Myself, I'm not sure
if strings (containing a number) should be accepted.

I've submitted a patch to Guido and am including it here.  This will
make all built-in sequences (strings, tuples and lists) perform an
implicit seq[int(subscr)] if subscr is not an int.  The subscripting
will still fail if int() fails.

  -Arcege

Index: Objects/abstract.c
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Objects/abstract.c,v
retrieving revision 2.27
diff -c -r2.27 abstract.c
*** abstract.c	1999/01/10 16:56:58	2.27
--- abstract.c	1999/07/09 12:30:03
***************
*** 228,233 ****
--- 228,234 ----
  	PyObject *key;
  {
  	PyMappingMethods *m;
+ 	PyObject *tmp, *v;
  
  	if (o == NULL || key == NULL)
  		return null_error();
***************
*** 239,244 ****
--- 240,250 ----
  	if (o->ob_type->tp_as_sequence) {
  		if (PyInt_Check(key))
  			return PySequence_GetItem(o, PyInt_AsLong(key));
+ 		else if ((tmp = PyNumber_Int(key)) != NULL) {
+ 			v = PySequence_GetItem(o, PyInt_AsLong(tmp));
+ 			Py_DECREF(tmp);
+ 			return v;
+ 		}
  		return type_error("sequence index must be integer");
  	}
  
***************
*** 252,257 ****
--- 258,265 ----
  	PyObject *value;
  {
  	PyMappingMethods *m;
+ 	PyObject *tmp;
+ 	int v;
  
  	if (o == NULL || key == NULL || value == NULL) {
  		null_error();
***************
*** 264,269 ****
--- 272,282 ----
  	if (o->ob_type->tp_as_sequence) {
  		if (PyInt_Check(key))
  			return PySequence_SetItem(o, PyInt_AsLong(key), value);
+ 		else if ((tmp = PyNumber_Int(key)) != NULL) {
+ 			v = PySequence_SetItem(o, PyInt_AsLong(tmp), value);
+ 			Py_DECREF(tmp);
+ 			return v;
+ 		}
  		type_error("sequence index must be integer");
  		return -1;
  	}
***************
*** 278,283 ****
--- 291,298 ----
  	PyObject *key;
  {
  	PyMappingMethods *m;
+ 	PyObject *tmp;
+ 	int v;
  
  	if (o == NULL || key == NULL) {
  		null_error();
***************
*** 290,295 ****
--- 305,315 ----
  	if (o->ob_type->tp_as_sequence) {
  		if (PyInt_Check(key))
  			return PySequence_DelItem(o, PyInt_AsLong(key));
+ 		else if ((tmp = PyNumber_Int(key)) != NULL) {
+ 			v = PySequence_DelItem(o, PyInt_AsLong(tmp));
+ 			Py_DECREF(tmp);
+ 			return v;
+ 		}
  		type_error("sequence index must be integer");
  		return -1;
  	}




More information about the Python-list mailing list