How can "k in d" be False, but "k in d.keys ()" will be True?

I have python code that throws a KeyError exception. So far, I have not been able to reproduce external operating environments, so I can not publish the test case below.

The code that throws the exception iterates through this loop:

for k in d.keys(): if condition: del d[k] 

The string del[k] throws an exception. I added a try/except clause around it and was able to determine that k in d is False, but k in d.keys() is True.

The d key is the associated instance methods of the old-style class.

The class implements __cmp__ and __hash__ , so when I focus my attention.

+7
python dictionary
source share
4 answers

k in d.keys() will check equality iteratively for each key, while k in d uses __hash__ , so your __hash__ can be broken (i.e. it returns different hashes for objects comparing the same ones).

+18
source share

A simple example of what's broken, for fun:

 >>> count = 0 >>> class BrokenHash(object): ... def __hash__(self): ... global count ... count += 1 ... return count ... ... def __eq__(self, other): ... return True ... >>> foo = BrokenHash() >>> bar = BrokenHash() >>> foo is bar False >>> foo == bar True >>> baz = {bar:1} >>> foo in baz False >>> foo in baz.keys() True 
+5
source share

Do not delete elements in d during iteration over it, save the keys that you want to remove in the list, and delete them in another loop:

 deleted = [] for k in d.keys(): if condition: deleted.append(k) for k in deleted: del d[k] 
+4
source share

What you do will throw a parallel modification exception in Java. d.keys() creates a list of keys that exist when it is called, but this list is now static. Changes to d will not change the saved version of d.keys() . Therefore, when you d.keys() over d.keys() , but delete the elements, you get the opportunity to change the key that no longer exists.

You can use d.pop(k, None) , which will return either the value displayed on k , or None if k not. This avoids the KeyError problem.

EDIT: for clarification, to prevent more phantom downmods (no negative feedback problems, just make it constructive and leave a comment so we can have a potentially informative discussion - I'm here to find out as well as help)

It is true that in this particular state he should not be mixed up . I just raised this as a potential problem, because if he uses the same coding scheme in another part of the program where he is not , so careful / lucky that he considers the data structure, such problems can arise. It does not even use a dictionary, but rather a class that implements certain methods, so you can relate to it in a similar way.

-one
source share

All Articles