为何字典内新建列表的两种赋值方式报错,另一种却正常?
问题:为何第98/100行代码报错,第99行能正常运行?
有人能解释为何第98行和第100行的代码运行报错,而第99行的代码能得到预期结果吗?如果result.get(event['event_string'], [])的结果真的是None(本不应该是),为何result[event['event_string']]会被赋值为列表?示例见第108行的event_ids[0]。
代码示例:
In [98]: result = {} ...: for event in event_ids: ...: result[event['event_string']] = result.get(event['event_string'], []).append(event['id']) ...: --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-98-5ffdfda0c2e0> in <module> 1 result = {} 2 for event in event_ids: ----> 3 result[event['event_string']] = result.get(event['event_string'], []).append(event['id']) 4 AttributeError: 'NoneType' object has no attribute 'append' In [99]: result = {} ...: for event in event_ids: ...: result[event['event_string']] = result.get(event['event_string'], []) ...: result[event['event_string']].append(event['id']) ...: In [100]: result = {} ...: for event in event_ids: ...: result[event['event_string']] = (result.get(event['event_string'], [])).append(event['id']) ...: --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-100-4a14efd8d356> in <module> 1 result = {} 2 for event in event_ids: ----> 3 result[event['event_string']] = (result.get(event['event_string'], [])).append(event['id']) 4 AttributeError: 'NoneType' object has no attribute 'append' In [108]: event_ids[0] Out[108]: {'id': 12539651, 'event_string': 'event 1o1'}
成功运行后result的条目示例:
"event alpha" : [12729182, 12747949, 12729716, 12708754]
核心解释
1. 列表append()方法的返回值是None
Python中列表的append()方法是原地修改列表,它不会返回修改后的列表,而是返回None。这是关键的第一个点。
2. 赋值操作的求值顺序:先算右边,再赋值左边
赋值语句中,等号右侧的表达式会被完整求值,得到结果后才会赋值给左侧的变量/字典键。结合上面的点,我们逐行分析:
第98/100行报错的原因
以第一次循环为例:
- 第一步:执行
result.get(event['event_string'], []),得到一个空列表(因为此时字典里还没有这个键)。 - 第二步:调用这个空列表的
append(event['id']),列表被修改(现在包含这个id),但append()返回None。 - 第三步:把
None赋值给result[event['event_string']],此时字典中这个键对应的值变成了None。
到第二次循环时:
- 执行
result.get(event['event_string'], []),因为键已经存在且值是None,所以返回None。 - 调用
None.append(),自然触发AttributeError,因为None没有append方法。
第99行正常运行的原因
同样看第一次循环:
- 第一步:
result[event['event_string']] = result.get(event['event_string'], []),把空列表赋值给字典键,此时键对应的值是列表。 - 第二步:调用
result[event['event_string']].append(event['id']),直接修改这个列表,没有覆盖键的值,键对应的值仍然是列表。
后续循环时,result.get(...)会拿到已存在的列表,调用append()修改列表,不会改变键对应的值类型,所以不会报错。
你疑惑的“为何result[event['event_string']]会被赋值为None”,本质是第一次循环时把append()的返回值None赋给了键,导致后续循环拿到None而非列表。
内容的提问来源于stack exchange,提问作者mohammad syed
相关产品推荐
相关产品推荐

