[Python-bugs-list] [ python-Bugs-698561 ] list.index() bhvr change > python2.x
SourceForge.net
noreply@sourceforge.net
Sun, 09 Mar 2003 12:31:53 -0800
Bugs item #698561, was opened at 2003-03-06 03:50
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=698561&group_id=5470
Category: None
>Group: Not a Bug
Status: Open
>Resolution: Invalid
Priority: 5
Submitted By: Armin Wittfoth (wittfoth)
>Assigned to: Tim Peters (tim_one)
Summary: list.index() bhvr change > python2.x
Initial Comment:
#!/usr/bin/python
"""
Between python1.x and python2.x there has been a major
undocumented (?) change in the behaviour of list.index().
(At least I have been unable to locate the relevant PEP.)
The following snippet illustrates this problem, though
the error
was encountered in a more complex real world situation,
where
a prototype system developed under python1.52 is being
realised
in python2.2.2.
"""
class Order :
def __init__ (self, ordernum) :
self.num = ordernum
def __eq__ (self, other) :
if (hasattr(other, 'num')) :
return self.num == other.num
else :
return self is other
if __name__ == '__main__' :
a = Order(123)
b = Order(234)
c = Order(345)
d = Order(123)
orders = [a, b, c, d]
for o in orders :
print orders.index(o)
"""
Under python1.4 (Solaris 5.6) and python1.52 (Linux
2.4.x) the
output is as would be expected :
0
1
2
3
Under python2.1.1, python2.2.2 and python2.3a2 (all Linux
2.4.x),the output is :
0
1
2
0
>From python2.x, list.index() apparently tests for
equivalence
rather than for identity. This is wrong, not the least
because
it breaks existing code (and more importantly, existing
design).
More fundamentally the problem is that it makes
dangerous the
use of the __eq__ hook, to redefine object equivalence,
and contravenes the 'principle of least surprise.'
As far as I know, testing for identity (is) cannot be
overriden,
whereas testing for equivalence (==) can. That being
the case
it is clearly safer to hang list.index() on the fixed
nature of
identity, rather than the redefinable nature of
equivalence.
"""
----------------------------------------------------------------------
>Comment By: Tim Peters (tim_one)
Date: 2003-03-09 15:31
Message:
Logged In: YES
user_id=31435
Closing as NotABug. The difference in behavior is due to
that __eq__ wasn't recognized as a special method at all
before rich comparisons were added, so the __eq__
method wasn't even invoked in 1.4. If you intend to use
your program across versions of Python that old, then you
need to restrict yourself to features that existed in Pythons
that old. In this case, define a __cmp__ method instead of
__eq__, and you'll see the same behavior under all Pythons
(__cmp__ has always been supported; __eq__ is a newer
feature).
Note that .index() has never tested for identity, always for
equality. In 1.4, your class doesn't define an equality
method, and when that's true Python falls back to
comparing objects by memory address.
----------------------------------------------------------------------
Comment By: Terry J. Reedy (tjreedy)
Date: 2003-03-09 14:16
Message:
Logged In: YES
user_id=593130
The documented behavior of list.index(o) is, and I suspect
always has been (at least the first part)
"s.index(x) return smallest i such that s[i] == x"
"Raises ValueError when x is not found in s."
If the matching were on identity, [some-literal].index(some-
literal) would raise ValueError instead of returning 0 if
some-literal were not interned or recorded in some way so
that both references were to the same object. Making
.index() dependent on the (changing) details of object
implementation and interning would make it both
surprising, version-dependent, and pretty useless.
Since .list() was added 12 years ago, there have been two
changes recorded in the CVS log: 1) flag multiple args as
an error and 2) switch from list_compare() to the newer
list_richcompare() (2 years ago).. This latter perhaps
fixed a previous bug.
When you write a .__eq__(s,o) method returning True, you
are saying that you *want* the interpreter to see s==0 as
True! So either don't do that, or write an 'iddex' function
that does what you want.
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=698561&group_id=5470