列表理解中的奇怪拆包
Weird unpacking in list comprehension
我在看a lecture from David Beazley。在第 23:20 分钟,他做了一些 "magic" 的拆包工作,我很难理解。
"magic line" 是
fail = [ { **row, 'DBA Name': row['DBA Name'].replace("'",'').upper() } for row in fail ]
我搜索过类似的示例,但找不到。你能解释一下这段代码中发生了什么吗?你能给我指出一些类似的例子吗?
该代码段在添加新元素的同时解压缩字典文字中已经存在的映射 row
。一个证明这一点的简化示例:
>>> r = {'a':1, 'b':2}
>>> {**r, 'Spam': 20}
{'Spam': 20, 'a': 1, 'b': 2}
此解包仅适用于 PEP 448 引入的 Python >= 3.5;在以前的版本中它是 SyntaxError
.
{**row}
只是解压字典(在 python-3.5+ 的文字中是允许的):
>>> row = {'DBA Name': "make 'this' now", 'b': 2}
>>> {**row}
{'DBA Name': "make 'this' now", 'b': 2}
本质上,这只是制作了 row
的副本,因为您将字典解压到字典中。
第二部分是正常的字典文字语法:
>>> {'DBA Name': row['DBA Name'].replace("'",'').upper() }
{'DBA Name': 'MAKE THIS NOW'}
"magic" 位是字典将唯一键映射到某个值,因此这本质上是 row
字典的副本,并用新值替换 'DBA Name'
键。这是有效的,因为文字是从左到右解释的:
>>> { **row, 'DBA Name': row['DBA Name'].replace("'",'').upper() }
{'DBA Name': 'MAKE THIS NOW', 'b': 2}
通常您只需创建字典的副本并替换键:
>>> newrow = row.copy()
>>> newrow['DBA Name'] = row['DBA Name'].replace("'",'').upper()
但这在理解中不起作用(理解中的赋值是 SyntaxError
)所以你需要一些 "magic"(或调用特殊方法)。
但您也可以使用嵌套理解来完成它(速度较慢但可能不那么神奇):
[ k: v.replace("'",'').upper() if key == 'DBA Name' else v
for row in fail
for k, v in row.items()]
缩进可能看起来有点不对劲,但我发现这样更容易形象化,您也可以只使用一行:
[k: v.replace("'",'').upper() if key == 'DBA Name' else v for row in fail for k, v in row.items()]
我在看a lecture from David Beazley。在第 23:20 分钟,他做了一些 "magic" 的拆包工作,我很难理解。
"magic line" 是
fail = [ { **row, 'DBA Name': row['DBA Name'].replace("'",'').upper() } for row in fail ]
我搜索过类似的示例,但找不到。你能解释一下这段代码中发生了什么吗?你能给我指出一些类似的例子吗?
该代码段在添加新元素的同时解压缩字典文字中已经存在的映射 row
。一个证明这一点的简化示例:
>>> r = {'a':1, 'b':2}
>>> {**r, 'Spam': 20}
{'Spam': 20, 'a': 1, 'b': 2}
此解包仅适用于 PEP 448 引入的 Python >= 3.5;在以前的版本中它是 SyntaxError
.
{**row}
只是解压字典(在 python-3.5+ 的文字中是允许的):
>>> row = {'DBA Name': "make 'this' now", 'b': 2}
>>> {**row}
{'DBA Name': "make 'this' now", 'b': 2}
本质上,这只是制作了 row
的副本,因为您将字典解压到字典中。
第二部分是正常的字典文字语法:
>>> {'DBA Name': row['DBA Name'].replace("'",'').upper() }
{'DBA Name': 'MAKE THIS NOW'}
"magic" 位是字典将唯一键映射到某个值,因此这本质上是 row
字典的副本,并用新值替换 'DBA Name'
键。这是有效的,因为文字是从左到右解释的:
>>> { **row, 'DBA Name': row['DBA Name'].replace("'",'').upper() }
{'DBA Name': 'MAKE THIS NOW', 'b': 2}
通常您只需创建字典的副本并替换键:
>>> newrow = row.copy()
>>> newrow['DBA Name'] = row['DBA Name'].replace("'",'').upper()
但这在理解中不起作用(理解中的赋值是 SyntaxError
)所以你需要一些 "magic"(或调用特殊方法)。
但您也可以使用嵌套理解来完成它(速度较慢但可能不那么神奇):
[ k: v.replace("'",'').upper() if key == 'DBA Name' else v
for row in fail
for k, v in row.items()]
缩进可能看起来有点不对劲,但我发现这样更容易形象化,您也可以只使用一行:
[k: v.replace("'",'').upper() if key == 'DBA Name' else v for row in fail for k, v in row.items()]