python中默认参数的工作原理

python中默认参数的工作原理,python,Python,我刚刚读了一篇文章:。这个问题仍然困扰着我。我将用下面的代码描述我的问题 >>>def foo(bar=[]): ... bar.append("baz") ... return bar >>> foo() ["baz"] >>> foo() ["baz", "baz"] 它不起作用,文章中的答案是list是一个multable类型,默认值在调用过程中会发生变化 def foo(bar=[]): if bar == []

我刚刚读了一篇文章:。这个问题仍然困扰着我。我将用下面的代码描述我的问题

>>>def foo(bar=[]):
...    bar.append("baz")
...    return bar
>>> foo()
["baz"]
>>> foo()
["baz", "baz"]
它不起作用,文章中的答案是list是一个multable类型,默认值在调用过程中会发生变化

def foo(bar=[]):
    if bar == []:bar=[]
...

它可以工作,那么有什么区别呢?

默认参数是在Python的函数定义中创建的。这意味着,当您提供一个列表作为默认参数时,对于未显式传递该参数的所有函数调用,该列表将保持不变。在第二个示例中,您将参数重新指定为不同的值。这将创建一个新列表并解决问题。对于这个“bug”/“特性”,更常见的解决方案是为默认参数指定一个
None
值,然后在函数顶部检查它。看起来是这样的:

def foo(bar=None):
    if bar is None:
        bar = []

但是,您在第二个示例中编写的代码达到了相同的效果。

默认参数是在Python的函数定义中创建的。这意味着,当您提供一个列表作为默认参数时,对于未显式传递该参数的所有函数调用,该列表将保持不变。在第二个示例中,您将参数重新指定为不同的值。这将创建一个新列表并解决问题。对于这个“bug”/“特性”,更常见的解决方案是为默认参数指定一个
None
值,然后在函数顶部检查它。看起来是这样的:

def foo(bar=None):
    if bar is None:
        bar = []

但是,您在第二个示例中编写的代码实现了相同的效果。

在代码中,您使用默认参数为
栏指定了一个新列表。现在,如果您修改新列表,更改当然不会显示在不同对象的默认参数中

典型的解决方案是将
None
指定给默认参数,并在函数开头显式检查它:

def foo(bar=None):
    if bar is None:
        bar = []
请注意,尽管它看起来与您的版本非常相似,但存在一些差异:

def foo(bar=[]):
    if bar == []:
        bar = []
    bar.append(1)

def foo2(bar=None):
    if bar is None:
        bar = []
    bar.append(1)

l = []
foo(l)
print l # []

l = []
foo2(l)
print l # [1]

在代码中,您可以使用默认参数将新列表指定给
bar
。现在,如果您修改新列表,更改当然不会显示在不同对象的默认参数中

典型的解决方案是将
None
指定给默认参数,并在函数开头显式检查它:

def foo(bar=None):
    if bar is None:
        bar = []
请注意,尽管它看起来与您的版本非常相似,但存在一些差异:

def foo(bar=[]):
    if bar == []:
        bar = []
    bar.append(1)

def foo2(bar=None):
    if bar is None:
        bar = []
    bar.append(1)

l = []
foo(l)
print l # []

l = []
foo2(l)
print l # [1]

第一个例子中的变化到底是什么,默认参数“bar”在调用后会发生变化吗?如果是,为什么第二个例子中的默认参数不会发生变化?还有一个追加操作,为什么它记不住bar的变化,但第一个是这样的?当您在函数中指定
bar
时,您没有更改函数定义中
bar
的默认值,您只是在特定函数调用的局部变量中更改它。这有助于理解对象是指向特定内存位置的指针。如果
id(obj1)
id(obj2)
具有相同的值,则它们是相同的对象。查看分配
bar=[]
前后的
id(bar)
,您将看到id已更改。因此,在第一个示例中,默认参数在追加操作后引用了一个新的RAM位置?哦,我盯着它看了很长时间,终于抓住了它的窍门:在第二个示例中,该条在一个新位置编辑,当我第二次调用它时,它指的是一个空列表。但是在第一次调用时,该条被就地编辑了。是吗?第一个示例中到底有什么变化,默认参数“bar”在调用后是否发生了变化?如果是,为什么第二个示例中的默认参数没有变化?还有一个追加操作,为什么它记不住bar的更改,而第一个却记不住?当您在函数中指定
bar
时,您并不是在函数定义中更改
bar
的默认值,而是在特定函数调用的局部变量中更改它。这有助于理解对象是指向特定内存位置的指针。如果
id(obj1)
id(obj2)
具有相同的值,则它们是相同的对象。查看分配
bar=[]
前后的
id(bar)
,您将看到id已更改。因此,在第一个示例中,默认参数在追加操作后引用了一个新的RAM位置?哦,我盯着它看了很长时间,终于抓住了它的窍门:在第二个示例中,该条在一个新位置编辑,当我第二次调用它时,它指的是一个空列表。但是在第一次调用时,该条被就地编辑。是吗?所以该条的更改发生在调用函数之后,在第一个示例中,追加操作完成后或调用完成后?@DavidPage:在第一个示例中,如果值为
[]
,则将
条更改为引用不同的列表,无论该值是来自默认参数还是来自调用者。然后列表被修改为
append
,但由于此时它的列表与作为参数调用方给出的列表不同,因此不会看到更改。谢谢,你们两个都帮了我很多忙。因此,在调用函数后,bar会发生更改,在第一个示例中,追加操作完成后或调用完成后?@DavidPage:在第一个示例中,如果值为
[]
,则将
条更改为引用不同的列表,无论该值是来自默认参数还是来自调用者。然后列表被修改为
append
,但由于此时列表与作为参数调用方给出的列表不同,因此不会看到更改。谢谢,你们两位都帮了我很多忙。