内置插件

时间:2018-05-15 14:15:28

标签: python

我们都知道'dreaded mutable default argument'

我很惊讶地发现至少有一个内置使用了一个可变的默认参数deepcopy(以及相关的__deepcopy__)。

def deepcopy(x, memo=None, _nil=[]):

source

这只是模块作者的一个忽视,还是有一些关于deepcopy行为的特别之处?

1 个答案:

答案 0 :(得分:5)

是的,这是故意的,该对象被用作唯一的哨兵对象。它永远不会发生变异,也不会检查列表对象内容。它的唯一目的是拥有一个可以在is测试中使用的唯一对象。

更常见的是使用None作为哨兵来测试是否未设置某些内容,但有时您需要允许None成为有效的设置值。在deepcopy()的实现中,_nil对象用于替换None

y = memo.get(d, _nil)
if y is not _nil:
    return y

这样可以设置memo[d] = None,因为如果memo.get(d)存在或缺失Nonememo[d]将返回>>> memo = {}; d = 'foo' >>> _nil = [] >>> memo.get(d) is None True >>> memo.get(d, _nil) is _nil True >>> memo[d] = None >>> memo.get(d) is None True >>> memo.get(d, _nil) is _nil False

None

如果您考虑使用自己独有的非object()哨兵对象,那么您现在可能想要使用object()。但是当编写deepcopy()函数时,_nil在Python语言中还没有存在。

_nil是使其成为局部变量的参数。这使查找_nil引用比模块中的全局更便宜,请参阅Why does Python code run faster in a function?这在一个很容易被称为很多的函数中很重要用于复制自定义对象的深层和宽层结构。因此,正如名称的最初下划线所示,# Get start time as time df['START_TIME'] = pd.to_datetime(df['START_TIME'],format='%H%M').dt.time 是一个实现细节。

另见Is there a way to set a default parameter equal to another parameter value?