在列表理解中奇怪的解包

时间:2017-08-18 14:12:01

标签: python python-3.x list-comprehension iterable-unpacking pep448

我在看a lecture from David Beazley。在23:20分钟,他做了一些"魔术"打开包装,我很难理解。

"魔术线"是

fail = [ { **row, 'DBA Name': row['DBA Name'].replace("'",'').upper() } for row in fail ]

我搜索过类似的例子,但我找不到任何例子。你能解释一下这段代码中发生了什么吗?你能指点我一些相似的例子吗?

2 个答案:

答案 0 :(得分:2)

该代码段在添加新元素时解压缩字典文字中已存在的映射row。一个简化的例子证明了这一点:

>>> r = {'a':1, 'b':2}    
>>> {**r, 'Spam': 20}
{'Spam': 20, 'a': 1, 'b': 2}

此解包仅在PEP 448引入的Pythons> = 3.5中可用;在以前的版本中,它是SyntaxError

答案 1 :(得分:1)

{**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'}

"魔法" bit是字典将唯一键映射到某个值,因此这实际上是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)所以你需要一些魔法" (或调用特殊方法)。

但你也可以通过嵌套理解来做到这一点(它的速度较慢但可能不那么神奇):

[        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()]