Should I Use 'Has_Key()' or 'In' on Python Dicts

Should I use 'has_key()' or 'in' on Python dicts?

in is definitely more pythonic.

In fact has_key() was removed in Python 3.x.

How to replace has_key in python3?

While the piecemeal solutions in the other answers will work, that approach is flawed simply because it's too easy to make a small mistake, miss a place that needs fixing, etc. The better solution is to just use the 2to3 converter. You could fix all of your files in one fell swoop with:

$ 2to3 -f has_key -w auto-selfcontrol.py

That only runs the has_key fixer which converts from dict.has_key(key) to key in dict. Sure you could make the fix yourself, but this is a case where simple programmatic fixers work just fine. You might just want to run it without -f has_key so it applies all the fixers at once, in case there are any other breaking changes that apply between Py2 and Py3.

2to3 handles just about everything automatically, with the exception of Py2 str type changes (where it's a code logic decision on whether a given str literal should be bytes or str in Py3) and integer division (where / might need to change to //, based on whether the computation is logically floating point division or floor division). But for has_key, it's pretty reliable.

Python dictionary has_key

It sounds like you have a bunch of conflating errors here.

First of all, a stack trace would show where the SyntaxError is, but you haven't included one in your posted code.

Second of all, you appear to want all the key-value pairs in x2 where the value appears in x1, not where the key appears in x1. That's harder, since x1 is not indexed by its values (obviously).

You could create such a set first:

x1_values = set(v for _, v in x1.items())

then use that as your selector

result = dict([(k, v) for k, v in x2.items() if v in x1_values])

Alternatively you could iterate over x1 and return the key-value pair in x2 if it exists.

result = dict([(v, x2[v]) for _, v in x1.items() if v in x2)

Note that in all my code snippets, I write key in dictionary rather than dictionary.has_key(key). The dict.has_key method is not supported in Python3, and speaking of which....


...it appears that you're writing code for a very old version of Python. Python2 is no longer supported, and you should update to the now decade-old Python3 ASAP. This code there looks like:

x1_values = {v for _, v in x1.items()}
result = {k: v for k, v in x2.items() if v in x1_values}

(surprisingly) python dict has_key faster than in

It's f in FDICT, not f in FDICT.keys(). Using keys builds a list of all the keys and goes through it one by one, whereas using f in FDICT uses an efficient hash-based lookup.

What is the time complexity of python dict has_key() method

Short answer: worst case it is O(n). But the average case time complexity is O(1). The worst case is however very rare.

When you do a lookup, the key is first double hashed (once by the type of the key and once by the dictionary). Based on that result, we know in which bucket we have to search, and we start searching.

It is however possible that hash collissions occur: in that case multiple keys are in the same bucket, so we have to search among multiple keys. Worst case all the keys are in the same bucket, and thus we fallback on linear search.

Hash collisions (with a large amount of keys) are however very rare. Usually it is safe to assume that - regardless of the size of the dictionary - the number of keys in the same bucket will be fixed.

The fact that it is O(n) had some interesting consequences on security. Say you have a server that stores and retrieves data in a dictionary. Then of course the response time will scale with such a lookup. Now a hacker can design input in such a way that all keys are placed in the same bucket(s). As a result lookup will slow down, and eventually the server will not respond in a reasonable time anymore. That's why Python has a flag -R for hash randomization. This will change the hash function for every run and therefore make it harder for a hacker to design such input.

No has_key() method for Python 3 dictionaries

Python 3 has dictionary key views instead, a much more powerful concept. Your code can be written as

some_dict.keys() & another_dict.keys()

in Python 3.x. This returns the common keys of the two dictionaries as a set.

This is also available in Python 2.7, using the method dict.viewkeys().

As a closer match of the original code, you could also use a list comprehension:

[key for key in some_dict if key in another_dict]

An even closer match of original code would be to use dict.__contains__(), which is the magic method corresponding to the in operator:

filter(another_dict.__contains__, some_dict.keys())

But please, don't use this code. I recommend going with the first version, which is the only one highlighting the symmetry between some_dict and another_dict.



Related Topics



Leave a reply



Submit