I was looking at the source code for the built-in argparse._AppendAction, which implements the "append" action, and puzzled over the way it is implemented:
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)
To break it down:
_ensure_valueis likedict.setdefaultfor attributes. That is, ifnamespacehas an attribute with the nameself.destthen it is returned, if not it is set to[]and returned._copy.copy(x)returns just a shallow copy. Whenxis a list it is exactly likelist(x)(but slower).- Then the item is appended to the copy of the list gotten from
namespace. - Finally the
self.destattribute ofnamespaceis overwritten with the copy, which should cause the old list to be garbage collected.
Why do it in such a roundabout and inefficient way, throwing away a whole list for each append? Why doesn't this suffice?
def __call__(self, parser, namespace, values, option_string=None):
items = _ensure_value(namespace, self.dest, [])
items.append(values)