我试图在字典中搜索关键字,但是我忘记添加 keys()
函数。尽管如此,我仍然得到了预期的答案。
为什么这两个表达式的结果相同?
key in dict
和
key in dict.keys()
我试图在字典中搜索关键字,但是我忘记添加 keys()
函数。尽管如此,我仍然得到了预期的答案。
为什么这两个表达式的结果相同?
key in dict
和
key in dict.keys()
key in dct
返回的结果与key in dct.keys()
相同,需要回顾一下历史。在Python 2中,人们通常使用dct.has_key(key)
来测试字典dct
中是否存在一个键。这在Python 2.2时发生了改变,推荐的方式变成了key in dct
,其基本上做了同样的事情:
在一个次要相关的更改中,
in
运算符现在可以用于字典,因此key in dict
现在等同于dict.has_key(key)
in
的行为是通过内部实现的__contains__
方法来实现的。其行为在Python语言参考-3数据模型中有记录:
(强调我的; Python中的字典是映射对象)
object.__contains__(self, item)
用于实现成员测试操作符。如果item在
self
中返回true,否则返回false。对于映射对象,这应该考虑映射的键而不是值或键值对。对于没有定义__contains__()
的对象,成员测试首先尝试通过__iter__()
进行迭代,然后是旧的序列迭代协议通过__getitem__()
,请参阅语言参考中的此部分。
has_key
方法,现在唯一正确的测试键是否存在的方法是key in dict
,如文档所述,保留a标签链接。
key in dct.keys()
从来都不是测试字典中是否存在键的正确方法。你示例的结果确实相同,但在Python 3上,key in dct.keys()
稍微慢一些,在Python 2上则非常慢。dct
中找到一个键 key
,key in dct
将返回true,这几乎是一个恒定时间操作 - 不管有两个还是一百万个键 - 它的时间复杂度在平均情况下是常数级别(O(1))。dct.keys()
创建一个包含所有键的列表;在Python 3中创建一个 视图,这两个对象都可以理解 key in x
。在Python 2中,它就像对于任何可迭代对象一样工作;值被迭代,并且只要一个值等于给定值(这里是key
),就会返回True
。key in dct.keys()
比key in dict
要慢得多(key in dct.keys()
的时间复杂度与键的数量成线性比例增长,为O(n) - dct.keys()
和key in key_list
都是O(n))。在Python 3中,由于view不会创建键列表,因此key in dct.keys()
的速度不会比key in dct
慢太多,访问仍然是O(1),但实际上至少会慢一定的常数值,并且它多了7个字符,所以通常没有使用它的实际理由,即使在Python 3上也是如此。Python数据模型规定,通常情况下成员测试是通过对序列进行迭代来实现的,除非容器对象提供了特殊方法__contains__
。
正如文档中进一步提到的那样,对于没有实现__contains__
特殊方法的对象,成员测试首先尝试通过__iter__()
进行迭代,然后再尝试通过__getitem__()
进行旧的序列迭代协议。
dict.keys()
返回的(Python 3.X)要么是一个迭代器,要么是一个字典视图,而在Python (2.X)中则返回一个序列(更确切地说是一个列表)。对于序列/列表的成员测试,其复杂度为O(n)
,而对于像哈希映射这样实现的字典对象或支持成员测试和迭代等操作的字典视图,则其复杂度为O(1)。dict.keys
返回的字典视图或序列上的成员测试。
<dict>.__iter__
不同于<dict>.keys()
-- 在 Python 2 中,keys
返回一个列表,在 Python 3 中,keys
返回一个“视图”。在 Python 2 中,<dict>.__iter__
等同于<dict>.iterkeys()
。此外,在对象中实现__iter__
不需要使用元类或内部类。 - jedwards