使用空字典作为默认参数的最具python风格的方式是什么?

使用空字典作为默认参数的最具python风格的方式是什么?,python,Python,在Python中,使用形式为x={}的默认参数通常无法达到预期目的,因为默认参数是在定义函数而不是调用函数时绑定的 惯例似乎是使用x=None将可变对象设置为默认参数,然后选中x is None以在调用函数时指定适当的默认值 因此,如果我想将x强制转换为默认为空的字典,我将使用以下内容: def f(x=None): x = dict(x) if x is not None else {} 然而,由于dict可以接受任何iterable,我也可以编写这个更简洁的版本: def f(x=

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

惯例似乎是使用
x=None
将可变对象设置为默认参数,然后选中
x is None
以在调用函数时指定适当的默认值

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

def f(x=None):
    x = dict(x) if x is not None else {}
然而,由于
dict
可以接受任何iterable,我也可以编写这个更简洁的版本:

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

以下哪一种是“正确”的方法?

这里没有正确或错误的答案,但我认为第一种方法更为惯用(这不会使第二种方法出错,或不好,或更糟,等等)。

惯用的风格是不要强制转换为
dict
;这样,就可以使用实现正确映射方法的任何对象

因此,最具python风格的方法是:

def f(x=None):
    if x is None:
        x = {}
然后使用映射方法

因此,您通常不应该将参数强制转换为dict。您声明您的API接受映射对象,并期望调用方执行强制转换


接受dict和iterable的唯一原因是当您希望支持允许重复键的有序键值对时,例如对于。在这种情况下,
dict
无法保留该信息,并且该方法不会将iterable强制转换为dict,而是将dict用作iterable。

需要指出的是,如果函数本身更改此
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
这样(后一种)原始的
x
就不会改变,所以不会出现问题

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