繁体   English   中英

在Python中设置应该是列表的参数的默认值的最佳实践?

[英]Best practice for setting the default value of a parameter that's supposed to be a list in Python?

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

def func(items=[]):
    print items

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

使用None作为默认值:

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

可变默认参数的问题在于它将在函数的所有调用之间共享 - 请参阅Python教程相关部分中的 “重要警告”。

我刚刚第一次遇到这个问题,我的想法是“好吧,我不想改变列表,所以我真正想要的是默认为不可变列表,所以如果我不小心Python会给我一个错误改变它。“ 不可变列表只是一个元组。 所以:

def func(items=()):
      print items

当然,如果你将它传递给真正想要列表的东西(例如isinstance(items,list)),那么这将让你陷入困境。 但无论如何这都是代码味道。

对于可变对象作为函数和方法声明中的默认参数,问题是评估和创建在完全相同的时刻发生。 python-parser读取函数头并在同一时刻对其进行评估。

大多数初学者认为每次调用都会创建一个新对象,但这不正确! 一个对象(在您的示例中为列表)是在DECLARATION时创建的,而不是在您调用方法时按需创建。

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

作为惯例,您使用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]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM