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