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. -- http://mail.python.org/mailman/listinfo/python-list