2017-08-18 72 views
2

我在观看a lecture from David Beazley。在23:20分钟,他做了一些“魔术”的解包,我很难理解。奇怪的解开列表理解

“神奇线”是

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

...我已经寻找类似的例子,但我找不到任何。你能解释一下这段代码发生了什么吗?你能指点我一些类似的例子吗?

+0

@JimFasarakisHilliard:其他职位是规范的“是什么''**后的意思,并有一个明确的答案涉及此案。 –

+0

@ MSeifert:同上你;我支持重复。 –

回答

2

这段代码将字典文字中的现有映射row解包,同时添加一个新元素。一个简单的例子证明了该:

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

这拆包仅在蟒蛇可用> = 3.5与PEP 448引入;在以前的版本中它是一个SyntaxError

+0

我不知道你可以在开箱时添加一个新元素。这是在官方文件?我无法找到它:/ –

+0

@alec_djinn是的,PEP 448描述了它,语言参考也是如此,请查看[字典显示](https://docs.python.org/3/reference/expressions.html #dictionary-displays)(见'**'上的句子)。 –

+0

谢谢!我错过了字典显示段落。 –

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

“神奇”的一点是,字典映射到某个值的唯一密钥,所以这基本上是一个副本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()]