字典方法
字典对象提供了丰富的方法,用于访问键、值、键值对,以及合并、更新等操作。理解这些方法的区别,尤其是 items() 和 iteritems() 的差异,是写出高效 Python 2 代码的关键。
获取所有键
keys():返回包含所有键的列表
d = {"a": 1, "b": 2, "c": 3}
print d.keys() # ['a', 'c', 'b'](Python 2 中返回列表)
# 可以修改返回的列表,不影响原字典
keys = d.keys()
keys.append("d")
print d # {'a': 1, 'c': 3, 'b': 2},原字典不变
iterkeys():返回键的迭代器(省内存)
print d.iterkeys() # <dictionary-keyiterator>
for key in d.iterkeys():
print key
遍历大字典时,iterkeys() 更优,因为它不创建完整的键列表。
获取所有值
values():返回包含所有值的列表
d = {"a": 1, "b": 2, "c": 3}
print d.values() # [1, 3, 2]
注意:值可以重复,返回的顺序与 keys() 对应。
itervalues():返回值的迭代器
for val in d.itervalues():
print val
获取所有键值对
items():返回包含所有 (key, value) 元组的列表
d = {"a": 1, "b": 2}
print d.items() # [('a', 1), ('b', 2)]
# 遍历
for key, value in d.items():
print key, value
iteritems():返回键值对的迭代器
for key, value in d.iteritems():
print key, value
iteritems() 是遍历字典的推荐方式,因为它不创建中间列表:
import sys
d = {i: i for i in range(1000000)}
# items() 创建包含 100 万个元组的列表
print sys.getsizeof(d.items()) # 约 40MB
# iteritems() 几乎不占用额外内存
print sys.getsizeof(d.iteritems()) # 约 56 字节
检查键是否存在
d = {"a": 1, "b": 2}
print "a" in d # True
print "z" in d # False
print "a" not in d # False
in 操作在字典中检查键,时间复杂度 O(1)。不要写成 d.keys() 来检查:
"a" in d # O(1),直接查哈希表
"a" in d.keys() # O(n),先创建列表再线性搜索
更新字典
update(other):用另一个字典或键值对序列更新当前字典
d1 = {"a": 1, "b": 2}
d2 = {"b": 20, "c": 3}
d1.update(d2)
print d1 # {'a': 1, 'c': 3, 'b': 20},b 被覆盖
# 也可以用关键字参数
d1.update(d=4, e=5)
print d1 # {'a': 1, 'c': 3, 'b': 20, 'e': 5, 'd': 4}
# 用键值对序列
d1.update([("f", 6), ("g", 7)])
setdefault(key, default):如果键不存在,设置默认值并返回;如果存在,返回现有值
d = {"a": 1}
print d.setdefault("a", 100) # 1,键已存在,返回原值
print d.setdefault("b", 2) # 2,键不存在,设置并返回 2
print d # {'a': 1, 'b': 2}
setdefault 常用于初始化计数器或分组:
# 按首字母分组
words = ["apple", "banana", "apricot", "cherry"]
groups = {}
for word in words:
first = word[0]
groups.setdefault(first, []).append(word)
print groups # {'a': ['apple', 'apricot'], 'c': ['cherry'], 'b': ['banana']}
删除操作
pop(key[, default]):删除键并返回值
d = {"a": 1, "b": 2}
val = d.pop("a")
print val # 1
print d # {'b': 2}
# 键不存在时
d.pop("z") # KeyError
d.pop("z", None) # 返回 None
popitem():删除并返回任意一个键值对
d = {"a": 1, "b": 2}
item = d.popitem()
print item # ('a', 1) 或 ('b', 2),顺序不确定
print d # 剩一个键值对
在 Python 2 中,popitem() 的"任意"实际上是随机的(取决于哈希表内部状态)。不要依赖它的顺序。
复制字典
d = {"a": 1, "b": [2, 3]}
# 浅拷贝
d2 = d.copy()
d2["a"] = 100
print d["a"] # 1,不受影响
d2["b"].append(4)
print d["b"] # [2, 3, 4],子列表被共享了!
# 深拷贝
import copy
d3 = copy.deepcopy(d)
d3["b"].append(5)
print d["b"] # [2, 3, 4],不受影响
方法速查表
| 方法 | 作用 | 返回类型 | 时间复杂度 |
|---|---|---|---|
keys() | 所有键 | 列表 | O(n) |
iterkeys() | 所有键 | 迭代器 | O(1) |
values() | 所有值 | 列表 | O(n) |
itervalues() | 所有值 | 迭代器 | O(1) |
items() | 所有键值对 | 列表 | O(n) |
iteritems() | 所有键值对 | 迭代器 | O(1) |
get(k, d) | 安全取值 | 值或默认值 | O(1) |
update(d) | 批量更新 | None | O(len(d)) |
setdefault(k, d) | 设置默认值 | 值 | O(1) |
pop(k) | 删除并返回 | 值 | O(1) |
popitem() | 删除任意项 | 键值对 | O(1) |
copy() | 浅拷贝 | 新字典 | O(n) |