使用空字典作为默认参数的最Pythonic方法是什么?

时间:2012-12-10 06:44:03

标签: python

使用x={}形式的默认参数通常无法实现Python中的预期目的,因为默认参数在定义函数时被绑定,而不是被调用。

约定似乎是将可变对象设置为x=None的默认参数,然后检查x is None以在调用函数时指定正确的默认值。

因此,如果我想将x转换为默认为空的字典,我会使用以下内容:

def f(x=None):
    x = dict(x) if x is not None else {}

但是,由于dict可以进行任何迭代,我还可以编写这个更简洁的版本:

def f(x=()):
    x = dict(x)

其中哪一种是“正确的”方法?

3 个答案:

答案 0 :(得分:6)

惯用样式是强制转换为dict;这样,有人可以使用实现正确映射方法的任何对象。

所以,最pythonic的方法是使用:

def f(x=None):
    if x is None:
        x = {}

然后只使用映射方法。

所以,你通常不应该为dict转换参数。您声明您的API 接受一个映射对象,并期望调用者进行转换。

同时接受dict和可迭代的唯一理由是,您希望支持允许重复键的有序键值对,例如urllib.urlencode function。在这种情况下,dict无法保留该信息,并且该方法不会将迭代转换为dict,而是将dict用作可迭代的。

答案 1 :(得分:1)

这里没有正确或错误的答案,但我会说第一个是更惯用的(不会使第二个错误,或者坏,或者更糟,等等。)

答案 2 :(得分:0)

需要指出的是,如果函数本身对此,则将空dict作为自变量仅是一个问题。如果仅读取dict,则不会发生任何问题。

如果要更改的dict,为什么将空的dict作为默认参数有意义?由于呼叫者尚未提供此消息,因此他们没有对此的引用,并且在呼叫后对dict所做的更改会丢失。

唯一有意义的情况是函数需要执行需要更改其输入版本的操作。在这种情况下,该函数可能应该创建更改后的版本而无需直接更改输入,例如:

dict

通过这种方式(后一种),原始# bad way: def f(x={}): x['newkey'] = 'newvalue' print(x) # do something with the extended x # probably better way: def f(x={}): new_dict = {} new_dict.update(x) new_dict.update({ 'newkey': 'newvalue' }) print(new_dict) # do something with the extended x 不会被更改,因此不会出现任何问题。

我知道可变默认参数问题是众所周知的,并且被认为是一个问题。但是我也有感觉,碰到它只是出现在其中的代码结构更深刻问题的征兆,我想在这篇文章中指出。或者换种说法:在一段结构合理的代码中,可变的默认参数永远不会导致实际问题。