Strange Behavior with Old-Style classes and implicit __contains__
Steven D'Aprano
steve at REMOVE.THIS.cybersource.com.au
Wed Apr 11 23:38:21 EDT 2007
On Wed, 11 Apr 2007 16:37:35 -0700, rconradharris wrote:
> A co-worker of mine came across some interesting behavior in the
> Python interpreter today and I'm hoping someone more knowledgeable in
> Python internals can explain this to me.
>
> First, we create an instance of an Old-Style class without defining a
> __contains__ but instead define a __getitem__ method in which we raise
> KeyError. Next we repeatedly use the 'in' operator to test to see
> whether something, a string, an int, etc is an attribute of this new
> instance.
>
> Here's the strange part: The first test will return False as if the
> __getitem__ was never called. The next test will raise a KeyError as
> we'd expect. The test after that will again return False. This goes on
> ad infinitum.
I can confirm that. It looks like __getitem__ is only being called every
second time.
class Parrot:
def __getitem__(self, n):
print "Checking index %s..." % n
raise KeyError
def tester(n):
parrot = Parrot()
results = []
for i in range(n):
try:
results.append(i in parrot)
except KeyError:
results.append("KeyError")
return results
Here are the results under Python 2.5:
>>> tester(10)
Checking index 0...
Checking index 0...
Checking index 0...
Checking index 0...
Checking index 0...
[False, 'KeyError', False, 'KeyError', False,
'KeyError', False, 'KeyError', False, 'KeyError']
And here are the results under Python 2.4.3:
>>> tester(10)
Checking index 0...
Checking index 0...
Checking index 0...
Checking index 0...
Checking index 0...
Checking index 0...
Checking index 0...
Checking index 0...
Checking index 0...
Checking index 0...
['KeyError', 'KeyError', 'KeyError', 'KeyError', 'KeyError',
'KeyError', 'KeyError', 'KeyError', 'KeyError', 'KeyError']
Looks like a bug to me.
--
Steven.
More information about the Python-list
mailing list