Why do `key in dict` and `key in dict.keys()` have the same output?

后端 未结 2 971
逝去的感伤
逝去的感伤 2021-02-19 07:29

I tried to search the keys in a dictionary, but I forgot to add the keys() function. I still got the expected answer.

Why is the result the same for these t

2条回答
  •  深忆病人
    2021-02-19 08:01

    To understand why key in dct returns the same result as key in dct.keys() one needs to look in the past. Historically in Python 2, one would test the existence of a key in dictionary dct with dct.has_key(key). This was changed for Python 2.2, when the preferred way became key in dct, which basically did the same thing:

    In a minor related change, the in operator now works on dictionaries, so key in dict is now equivalent to dict.has_key(key)

    The behaviour of in is implemented internally in terms of the __contains__ dunder method. Its behaviour is documented in the Python language reference - 3 Data Model:

    object.__contains__(self, item)

    Called to implement membership test operators. Should return true if item is in self, false otherwise. For mapping objects, this should consider the keys of the mapping rather than the values or the key-item pairs. For objects that don’t define __contains__(), the membership test first tries iteration via __iter__(), then the old sequence iteration protocol via __getitem__(), see this section in the language reference.

    (emphasis mine; dictionaries in Python are mapping objects)

    In Python 3, the has_key method was removed altogether and now there the correct way to test for the existence of a key is solely key in dict, as documented.


    In contrast with the 2 above, key in dct.keys() has never been the correct way of testing whether a key exists in a dictionary. The result of both your examples is indeed the same, however key in dct.keys() is slightly slower on Python 3 and is abysmally slow on Python 2.

    key in dct returns true, if the key is found as a key in the dct in almost constant time operation - it does not matter whether there are two or a million keys - its time complexity is constant on average case (O(1))

    dct.keys() in Python 2 creates a list of all keys; and in Python 3 a view of keys; both of these objects understand the key in x. With Python 2 it works like for any iterable; the values are iterated over and True is returned as soon as one value is equal to the given value (here key).

    In practice, in Python 2 you'd find key in dct.keys() much slower than key in dict (key in dct.keys() scales linearly with the number of keys - its time complexity is O(n) - both dct.keys(), which builds a list of all keys, and key in key_list are O(n))

    In Python 3, the key in dct.keys() won't be much slower than key in dctas the view does not make a list of the keys, and the access still would be O(1), however in practice it would be slower by at least a constant value, and it is 7 more characters, so there is usually practically no reason to use it, even if on Python 3.

提交回复
热议问题