我正在查看实现动作的内置argparse._AppendAction的源代码,并对它的实现方式"append"
感到困惑:
def __call__(self, parser, namespace, values, option_string=None):
items = _copy.copy(_ensure_value(namespace, self.dest, []))
items.append(values)
setattr(namespace, self.dest, items)
分解它:
_ensure_value
就像dict.setdefault
属性一样。也就是说,如果namespace
有一个带有名称的属性,self.dest
则返回它,如果没有,则将其设置为[]
并返回。_copy.copy(x)
只返回一个浅拷贝。什么时候x
是一个列表,它完全一样list(x)
(但速度较慢)。- 然后将该项目附加到从 获取的列表的副本
namespace
中。 - 最后, 的
self.dest
属性namespace
被副本覆盖,这应该会导致旧列表被垃圾收集。
为什么要以如此迂回和低效的方式进行,为每个附加项扔掉一个完整的列表?为什么这还不够?
def __call__(self, parser, namespace, values, option_string=None):
items = _ensure_value(namespace, self.dest, [])
items.append(values)