《Python编程的术与道:Python语言入门》视频课程
《Python编程的术与道:Python语言入门》视频课程链接:https://edu.csdn.net/course/detail/27845
字典推导 (Dictionary Comprehension)
推导是从迭代器创建Python数据结构的一种简洁方式。
有了推导,就可以使用不太冗长的语法将循环和条件测试结合起来。
推导被认为是更加Python化,并且在很多情况下有用。
什么是字典推导?
字典推导是一种通过对迭代器中的每个元素应用表达式来构建新字典的方法。字典推导可以从任何以键值对作为元素的可迭代对象中构建出字典。
它省去了编写多行代码的麻烦,并使代码更可读。
假设要创建数字和其平方的字典。
可以通过一次将一元素插入一个空字典来构建这样的字典:
D = {}
D[0] = 0
D[1] = 1
D[2] = 4
D[3] = 9
D[4] = 16
print(D) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
或者,可以使用一个迭代器和range()
函数:
D = {}
for x in range(5):
D[x] = x**2
print(D) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
两种方法在这里产生相同的结果。 但是,构建字典的更加Python方式是使用字典推导。
字典推导的一般语法为:
下面是字典推导如何构建字典的例子:
D = {x: x**2 for x in range(5)}
print(D) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
在上面的示例中,字典推导分为两个部分。
- 第一部分,在每次迭代中收集表达式的键/值结果,并使用它们填充一个新的字典。
2.第二部分与for循环完全相同。在该循环中,告诉Python要进行迭代。 每次循环遍历可迭代项时,Python都会将一个单独的元素赋值给变量x。
更多例子
以下是一些示例,有助于理解字典推导。
例子1
字典推导可以迭代任何类型的可迭代对象,例如列表、字符串、文件、range以及任何其他支持迭代协议的对象。
这是一个简单的字典推导,它使用字符串作为可迭代对象。
D = {c: c * 3 for c in 'RED'}
print(D) # {'R': 'RRR', 'E': 'EEE', 'D': 'DDD'}
{'R': 'RRR', 'E': 'EEE', 'D': 'DDD'}
例子2
在字典推导中,也可以像值一样使用表达式来计算键。
示例:在字典的键和值上调用方法
L = ['ReD', 'GrEeN', 'BlUe']
D = {c.lower(): c.upper() for c in L}
print(D)
{'red': 'RED', 'green': 'GREEN', 'blue': 'BLUE'}
提取字典的子集
有时想创建一个词典,该词典是另一个词典的子集。
使用字典推导很容易做到这一点。
示例:从字典中提取特定键
D = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F'}
selectedKeys = [0, 2, 5]
X = {k: D[k] for k in selectedKeys}
print(X) # {0: 'A', 2: 'C', 5: 'F'}
{0: 'A', 2: 'C', 5: 'F'}
过滤字典内容
假设要删除选定的键来制作新词典。
示例:从字典中删除特定键
D = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F'}
removeKeys = [0, 2, 5]
X = {k: D[k] for k in D.keys() - removeKeys}
print(X)
{1: 'B', 3: 'D', 4: 'E'}
反转映射/反向查找
字典推导的另一种用法是在字典中反转key:value对。
当要使用字典中的值来检索键时,此功能很有用。
D = {0: 'red', 1: 'green', 2: 'blue'}
R = {v: k for k,v in D.items()}
print(R)
{'red': 0, 'green': 1, 'blue': 2}
带有enumerate的字典推导
有时想从列表中创建字典,列表索引号为键,列表元素为值。
为此,将列表包装在enumerate()
函数中,并将其作为迭代传递给字典推导。
L = ['red', 'green', 'blue']
D = {k:v for k,v in enumerate(L)}
print(D) # {0: 'red', 1: 'green', 2: 'blue'}
{0: 'red', 1: 'green', 2: 'blue'}
具有元素索引的此类词典在各种情况下(例如逐行读取文件)通常很有用。
D = {ix: line for ix, line in enumerate(open('./files/test.txt'))}
print(D)
{0: '1) This is a test file\n', 1: '2) With multiple lines of data...\n', 2: '3) Third line\n', 3: '4) Fourth line\n', 4: '5) Fifth line\n', 5: '6) Sixth line\n', 6: '7) Seventh line\n', 7: '8) Eighth line\n', 8: '9) Ninth line\n', 9: '10) Tenth line'}
用推导初始化字典
字典推导对于从键的列表初始化字典也很有用,其方式与fromkeys
方法大致相同。
示例:使用默认值初始化字典
keys = ['red', 'green', 'blue']
# default value '0'
D = {k: 0 for k in keys}
print(D) # {'red': 0, 'green': 0, 'blue': 0}
{'red': 0, 'green': 0, 'blue': 0}
# default value 'None'
D = {k: None for k in keys}
print(D) # {'red': None, 'green': None, 'blue': None}
{'red': None, 'green': None, 'blue': None}
动态初始化字典的标准方法是将其键和值与zip组合在一起,然后将结果传递给dict()
函数。
但是,可以通过字典推导获得相同的结果。
Example: 创建带有zipped键/值列表的字典
keys = ['name', 'age', 'job']
values = ['Bob', 25, 'Dev']
D = dict(zip(keys, values))
print(D) # {'name': 'Bob', 'age': 25, 'job': 'Dev'}
D = {k: v for (k, v) in zip(keys, values)}
print(D) # {'name': 'Bob', 'age': 25, 'job': 'Dev'}
{'name': 'Bob', 'age': 25, 'job': 'Dev'}
{'name': 'Bob', 'age': 25, 'job': 'Dev'}
带有if子句的字典推导
词典推导可以具有可选的关联if子句,以从结果中过滤出元素。
如果if子句不为真,则跳过iterable的相应元素。
以下示例收集一个范围内偶数项的平方。
D = {x: x**2 for x in range(6) if x % 2 == 0}
print(D)
{0: 0, 2: 4, 4: 16}
此字典推导与包含if语句的for循环相同:
D = {}
for x in range(5):
if x % 2 == 0:
D[x] = x**2
print(D) # {0: 0, 2: 4, 4: 16}
{0: 0, 2: 4, 4: 16}
嵌套字典推导
词典推导中的初始值可以是任何表达式,包括另一个词典推导。
例如,这是一个简单的列表推导,它使用嵌套的for子句。
Example: Nested dictionary comprehension
D = {(k,v): k+v for k in range(2) for v in range(2)}
print(D)
# {(0, 1): 1, (1, 0): 1, (0, 0): 0, (1, 1): 2}
{(0, 0): 0, (0, 1): 1, (1, 0): 1, (1, 1): 2}
这等价于:
D = {}
for k in range(2):
for v in range(2):
D[(k,v)] = k+v
print(D)
# {(0, 1): 1, (1, 0): 1, (0, 0): 0, (1, 1): 2}
{(0, 0): 0, (0, 1): 1, (1, 0): 1, (1, 1): 2}