Hello,
I came accross what i think is a serious bug in the python interpreter.
Membership testing seems not to work for list of objects when these
objects have a user-defined __cmp__ method.
It is present in Python 2.3 and 2.4. I don''t know about other versions.
The following code illustrates the bug:
from random import choice
class OBJ:
def __init__(self,identifier):
self.id=identifier
self.allocated=0
def __cmp__(self,other):
return cmp(other.allocated,self.allocated)
mylist=[OBJ(i) for i in range(20)]
excluded=[obj for obj in mylist if obj.id>choice(range(20))]
for obj in mylist:
if obj in excluded:
assert obj.id in [objt.id for objt in excluded]
continue
Running the above snippet will trigger the assert. The culprit seems to
be the __cmp__ method which sorts on a key with constant value.
Best regards
Alain
解决方案Why would it be a bug? You''ve made it so that every instance of OBJ is
equal to every other instance of OBJ. The behaviour is as expected.
al********@yahoo.fr wrote:Hello,
I came accross what i think is a serious bug in the python interpreter.
Membership testing seems not to work for list of objects when these
objects have a user-defined __cmp__ method.
It is present in Python 2.3 and 2.4. I don''t know about other versions.
The following code illustrates the bug:
from random import choice
class OBJ:
def __init__(self,identifier):
self.id=identifier
self.allocated=0
def __cmp__(self,other):
return cmp(other.allocated,self.allocated)
mylist=[OBJ(i) for i in range(20)]
excluded=[obj for obj in mylist if obj.id>choice(range(20))]
for obj in mylist:
if obj in excluded:
assert obj.id in [objt.id for objt in excluded]
continue
I presume you just put the "continue" in there for fun?
for obj in mylist:
.... print obj in excluded
....
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True OBJ(0) == OBJ(1)
True
Running the above snippet will trigger the assert. The culprit seems to
be the __cmp__ method which sorts on a key with constant value.
Well indeed. As far as I can see your objects will all test equal. Did
you mean the __cmp__ method to return cmp(other.id, self.id)?
regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/
There is definitely a bug.
Maybe the follownig snippet is more clear:
class OBJ:
def __init__(self,identifier):
self.id=identifier
self.allocated=0
#def __cmp__(self,other):
#return cmp(other.allocated,self.allocated)
mylist=[OBJ(i) for i in range(10)]
excluded=[obj for obj in mylist if obj.id in [2,4,6,8]]
exclusion_list_by_id=[2,4,6,8]
print ''exclusion list by id='',exclusion_list_by_id
for obj in mylist:
print ''current obj='',obj.id,
if obj in excluded:
print '' ---> THIS OBJECT IS EXCLUDED''
assert obj.id in exclusion_list_by_id
continue
If you uncomment the two lines, the assert will be erroneously
triggered.
Alain