python function default parameter is evaluated only once?
我是一个Python初学者,正在阅读"Python教程",它说如果我们有一个函数:
1 2 3 4 5 6 | def f(a, L=[]): L.append(a) return L print f(1) print f(2) print f(3) |
这将打印
1 2 3 | [1] [1, 2] [1, 2, 3] |
因为默认值只计算一次,而列表是可变对象。我能理解。
它说继续,如果我们不希望在子后续调用之间共享默认值,我们可以:
1 2 3 4 5 6 7 8 | def f(a, L=None): if L is None: #line 2 L = [] L.append(a) return L print f(1) print f(2) print f(3) |
这将输出:
1 2 3 | [1] [2] [3] |
但是为什么呢?如何解释这一点。我们知道默认值只计算
python按值将参数传递给函数;因此对于对象,传递的值是对对象的引用,而不是对象的新副本。
这一点,连同以下部分的官方文件,帮助我更好地理解它(强调我的):
Default parameter values are evaluated [...] when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same"pre-computed" value is used for each call. This is especially important to understand when a default parameter is a mutable object, such as a list or a dictionary: if the function modifies the object (e.g. by appending an item to a list), the default value is in effect modified. [...] A way around this is to use None as the default, and explicitly test for it in the body of the function [...]
把它们放在一起:
如果将参数的默认值定义为可变对象(如
但是,由于
希望有帮助!我确实认为教程应该有更好的措辞,因为一开始我也被它搞糊涂了。
"默认值只计算一次"并不意味着具有默认值的参数在函数调用之间保留其值。这意味着,您指定的表达式(
我认为这是因为列表是可变对象,而值"无"是不可变的。
对于第一个函数,变量L在函数环境之外(在函数定义中),它引用一个空列表。然后在函数环境中对此列表进行更改,但是由于列表是可变的,因此函数环境之外的变量l引用了这个现在变了的列表,并且每次调用函数时,更改都会传播。
对于第二个函数,变量l也在函数环境之外(在函数定义中),但这次它指的是无,这是不可变的。现在,您在函数环境中所做的每一个更改都不会影响函数环境之外的l所指的内容。函数环境中的变量l在您更改时引用了不同的内容。首先,它引用一个空列表,然后是一个附加值的列表。然后返回此列表。下次调用函数时,使用函数环境之外的变量l来调用它,该变量没有更改,但仍然引用none。
希望这是有道理的。
在第二个示例中,您有一个变量
然而,在第一个示例中,l在函数声明处设置为新列表一次。每次调用函数时,L都不会重置为
发生的情况如下:
当调用python函数时,它是在定义它的环境中进行评估的,而不是在调用它的环境中进行评估的,尽管第二部分是次要的(没有双关语),以回答您的问题。
默认参数在函数定义时只计算一次。这将创建一个闭包。把闭包看作函数代码+定义函数的环境。
因此,在定义函数时,
本教程还提到:
默认值在定义范围内的函数定义点进行计算(并且定义范围是闭包的一部分,以及函数代码)。
http://docs.python.org/2/tutorial/controlflow.html默认参数值