Apu*_*lol 16 python dictionary generator generator-expression
我有一个字典列表,如下所示:
lst = [{'a': 5}, {'b': 6}, {'c': 7}, {'d': 8}]
Run Code Online (Sandbox Code Playgroud)
我写了一个生成器表达式,如:
next((itm for itm in lst if itm['a']==5))
Run Code Online (Sandbox Code Playgroud)
现在奇怪的是,虽然这适用于它的键值对,'a'
但下次会为所有其他表达式抛出错误.表达:
next((itm for itm in lst if itm['b']==6))
Run Code Online (Sandbox Code Playgroud)
错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
KeyError: 'b'
Run Code Online (Sandbox Code Playgroud)
Wil*_*sem 33
这并不奇怪.对于每一itm
个人lst
.它将首先评估过滤条款.现在,如果是filter子句itm['b'] == 6
,它将尝试'b'
从该字典中获取密钥.但由于第一个字典没有这样的密钥,它会引发错误.
对于第一个过滤器示例,这不是问题,因为第一个字典有一个'a'
键.的next(..)
是仅在感兴趣的第一由发电机发射的元件.所以它永远不会要求过滤更多的元素.
您可以.get(..)
在此处使查找更加安全:
next((itm for itm in lst if itm.get('b',None)==6))
Run Code Online (Sandbox Code Playgroud)
如果字典没有这样的键,则该.get(..)
部分将返回None
.并且由于None
不等于6,因此过滤器将省略第一个字典并进一步查看另一个匹配.请注意,如果未指定默认值,None
则为默认值,因此等效语句为:
next((itm for itm in lst if itm.get('b')==6))
Run Code Online (Sandbox Code Playgroud)
我们也可以省略生成器的括号:只有当有多个参数时,我们才需要这些附加的括号:
next(itm for itm in lst if itm.get('b')==6)
Run Code Online (Sandbox Code Playgroud)
pok*_*oke 15
分别看看你的生成器表达式:
(itm for itm in lst if itm['a']==5)
Run Code Online (Sandbox Code Playgroud)
这将收集列表中的所有项目itm['a'] == 5
.到现在为止还挺好.
当你调用next()
它时,你告诉Python 从该生成器表达式生成第一个项目.但只有第一个.
因此,当您有条件时itm['a'] == 5
,生成器将获取列表的第一个元素,{'a': 5}
并对其执行检查.条件为true,因此该项由生成器表达式生成并返回next()
.
现在,当您将条件更改为时itm['b'] == 6
,生成器将再次获取列表的第一个元素{'a': 5}
,并尝试使用键获取元素b
.这将失败:
>>> itm = {'a': 5}
>>> itm['b']
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
itm['b']
KeyError: 'b'
Run Code Online (Sandbox Code Playgroud)
它甚至没有机会查看第二个元素,因为它在尝试查看第一个元素时已经失败了.
要解决此问题,您必须避免使用可以在KeyError
此处引发的表达式.您可以使用dict.get()
尝试检索值而不引发异常:
>>> lst = [{'a': 5}, {'b': 6}, {'c': 7}, {'d': 8}]
>>> next((itm for itm in lst if itm.get('b') == 6))
{'b': 6}
Run Code Online (Sandbox Code Playgroud)
如果词典中没有键,显然itm['b']
会提出一个.一种方法是做KeyError
'b'
next((itm for itm in lst if 'b' in itm and itm['b']==6))
Run Code Online (Sandbox Code Playgroud)
如果你不想None
在任何词典中,那么你可以简化它
next((itm for itm in lst if itm.get('b')==6))
Run Code Online (Sandbox Code Playgroud)
(这与你比较时的工作方式相同6
,但是如果要进行比较会产生错误的结果None
)
或安全地使用占位符
PLACEHOLDER = object()
next((itm for itm in lst if itm.get('b', PLACEHOLDER)==6))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2677 次 |
最近记录: |