在 Python 中迭代一个字典时,为什么必须调用. item() ?

为什么必须调用 items()来迭代字典中的键值对。

dic = {'one': '1', 'two': '2'}
for k, v in dic.items():
print(k, v)

为什么这不是在字典上迭代的默认行为呢

for k, v in dic:
print(k, v)
83344 次浏览

我的猜测是: 使用完整的 tuple 对于循环来说更加直观,但是对于使用 in测试成员资格来说可能就不那么直观了。

if key in counts:
counts[key] += 1
else:
counts[key] = 1

如果您必须同时为 in指定键和值,那么这段代码就不能正常工作。我很难想象用例中你会检查键和值是否都在字典中。只测试钥匙要自然得多。

# When would you ever write a condition like this?
if (key, value) in dict:

现在不需要 in操作符和 for ... in操作相同的项。在实现方面,它们是不同的操作(__contains____iter__)。但是,这种小小的不一致会让人有些困惑,并且,嗯,不一致。

对于每个 python 容器 C,期望是

for item in C:
assert item in C

如果 in(循环子句)的一个意思与另一个(存在检查)的意思完全不同,不会感到惊讶吗?我当然愿意!对于列表、集合、元组,它自然是这样工作的... ..。

因此,当 C是一个字典时,如果 in要在 for循环中产生键/值元组,那么根据最小惊讶原则,in也必须在遏制检查中将这样一个元组作为其左边的操作数。

那会有多大用处?实际上非常无用,基本上使 if (key, value) in C成为 if C.get(key) == value的同义词——这是一个检查,我相信我可能已经执行过,或者想要执行的,比 if k in C实际执行的 手段少100倍,检查键 只有的存在并完全忽略值。

另一方面,只想在键上循环是很常见的,例如:

for k in thedict:
thedict[k] += 1

同时拥有价值并不会特别有帮助:

for k, v in thedict.items():
thedict[k] = v + 1

实际上有些不那么清晰,不那么简洁。(请注意,items是获取键/值对的“正确”方法的原拼法,不幸的是,那时这种访问器返回整个列表,所以为了支持“只是迭代”,必须引入另一种拼写方法,而 iteritems就是这样——在 Python 3中,与以前的 Python 版本向后兼容性约束大大削弱,它又变成了 items)。