Issue698561
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2003-03-06 08:50 by wittfoth, last changed 2022-04-10 16:07 by admin. This issue is now closed.
Messages (3) | |||
---|---|---|---|
msg14994 - (view) | Author: Armin Wittfoth (wittfoth) | Date: 2003-03-06 08:50 | |
#!/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. """ |
|||
msg14995 - (view) | Author: Terry J. Reedy (terry.reedy) * ![]() |
Date: 2003-03-09 19:16 | |
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. |
|||
msg14996 - (view) | Author: Tim Peters (tim.peters) * ![]() |
Date: 2003-03-09 20:31 | |
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. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-10 16:07:25 | admin | set | github: 38114 |
2003-03-06 08:50:37 | wittfoth | create |