设置';它应该是Python中的列表吗?

设置';它应该是Python中的列表吗?,python,default-value,pylint,Python,Default Value,Pylint,我有一个Python函数,它将列表作为参数。如果我将参数的默认值设置为空列表,如下所示: def func(items=[]): print items Pylint会告诉我“危险的默认值[]作为参数”。所以我想知道这里的最佳实践是什么?使用None作为默认值: def func(items=None): if items is None: items = [] print items 可变默认参数的问题在于,它将在函数的所有调用之间共享—请参见。中的

我有一个Python函数,它将列表作为参数。如果我将参数的默认值设置为空列表,如下所示:

def func(items=[]):
    print items

Pylint会告诉我“危险的默认值[]作为参数”。所以我想知道这里的最佳实践是什么?

使用
None
作为默认值:

def func(items=None):
    if items is None:
        items = []
    print items

可变默认参数的问题在于,它将在函数的所有调用之间共享—请参见。

中的“重要警告”,将可变对象作为函数和方法声明中的默认参数—问题在于,求值和创建完全在同一时刻发生。python解析器读取函数头并同时对其求值

大多数人认为每次调用都会创建一个新对象,但这是不对的!一个对象(在您的示例中是一个列表)是在声明时创建的,而不是在调用该方法时按需创建的

对于imutable对象,这不是问题,因为即使所有调用共享同一个对象,它也是imutable的,因此它的属性保持不变


作为惯例,您使用默认值的
None
对象来指示默认初始化的使用,默认初始化现在可以在函数体中进行,函数体自然会在调用时进行评估

此外,为了更好地理解python是什么,这里是我的主题片段:

from functools import wraps
def defaultFactories(func):
    'wraps function to use factories instead of values for defaults in call'
    defaults = func.func_defaults
    @wraps(func)
    def wrapped(*args,**kwargs):
        func.func_defaults = tuple(default() for default in defaults)
        return func(*args,**kwargs)
    return wrapped

def f1(n,b = []):
    b.append(n)
    if n == 1: return b
    else: return f1(n-1) + b

@defaultFactories
def f2(n,b = list):
    b.append(n)
    if n == 1: return b
    else: return f2(n-1) + b

>>> f1(6)
[6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1]
>>> f2(6)
[1, 2, 3, 4, 5, 6]

我第一次遇到这个问题,我的直接想法是“好吧,我无论如何都不想改变列表,所以我真正想要的是默认为一个不可变列表,这样如果我不小心改变了它,Python会给我一个错误。”不可变列表只是一个元组。因此:

def func(items=()): print items def func(项目=()): 打印项目
当然,如果您将它传递给确实需要列表的对象(例如isinstance(items,list)),那么这会给您带来麻烦。但这毕竟是一种代码味道。

啊,哇,我很惊讶人们知道这一点。=)我非常讨厌python的这个特性,所以我编写了自己的decorator库来支持
func(items=new([])
语法。谢谢!看起来Python认为没有一种是完全不同于列表的类型,所以我想知道Python是否可以将参数的默认值设置为不同类型(如Python)(我知道Python是一种没有类型的语言,但我来自C++ + LOL)?@ WIM:我想你是指静态的,而不是强的;python是强类型的,但它是动态类型的。您不必每次都检查它,只有当您预期它不会是您认为应该是的时候。就像在C++中检查指针/引用是否为空。您不会每次都检查它,但在许多情况下,防范它是有意义的。我通常会编写
items=items或[]
,如果我希望
items
是一个可移植的类型。这是每一个python新手都会做一两次的事情,派林阻止您编写一个可怕的bug真是太酷了!另一个非常简单的技巧是使用空元组:
def func(items=())
。元组是不可变的,因此pylint会关闭,但问题要求提供一个列表,因此这并不总是相关的或可能的。如果在函数中需要复制,请使用
my\u copy=list(items)
。你对一个常见的问题提出了一个简单而聪明的解决方案。