Python函数:可选参数计算一次?
Python教程说明了以下内容: 重要警告:默认值仅计算一次。这就不同了 当默认值为可变对象时,例如列表、字典或most的实例 上课。例如,下面的函数累积上传递给它的参数 后续电话:Python函数:可选参数计算一次?,python,Python,Python教程说明了以下内容: 重要警告:默认值仅计算一次。这就不同了 当默认值为可变对象时,例如列表、字典或most的实例 上课。例如,下面的函数累积上传递给它的参数 后续电话: def f(a, L=[]): L.append(a) return L print f(1) print f(2) print f(3) 这会打印出来 [1] [1, 2] [1, 2, 3] 我不太明白“只评估一次”在内存管理方面的含义。显然,当函数第一次被调用并存储在单独的内存地址中时,
def f(a, L=[]):
L.append(a)
return L
print f(1)
print f(2)
print f(3)
这会打印出来
[1]
[1, 2]
[1, 2, 3]
我不太明白“只评估一次”在内存管理方面的含义。显然,当函数第一次被调用并存储在单独的内存地址中时,即使在函数结束后,函数的默认值也会被计算一次。(据我了解,函数结束后,所有局部变量都应该释放?)
我说的对吗?在Python中,函数也是对象,默认值与函数对象一起存储。默认值是而不是局部变量;只是在调用函数时,参数在没有给出显式值的情况下绑定到默认值 当Python遇到
def():
语句时,它会在那里为您创建一个函数对象;这是“定义时间”;函数不是被调用的,只是被创建的。然后,在函数对象的属性中计算并存储默认值
然后,当您调用该函数时,默认值已经创建,并且在您没有为参数提供更具体的值时使用。由于默认值与函数对象一起存储,因此可以在函数调用之间看到可变对象的更改
当然,局部变量仍然会被清除,但由于它们是引用(Python中的所有标识符都是),因此它们绑定到的对象只有在没有其他对象引用它们时才会被清除
您可以查看任何函数对象的默认值:
>>> def foo(bar='spam', eggs=[]):
... eggs.append(bar)
... return eggs
...
>>> foo.__defaults__
('spam', [])
>>> foo()
['spam']
>>> foo.__defaults__
('spam', ['spam'])
>>> foo() is foo.__defaults__[1]
True
foo()
函数有一个\uuuuu defaults\uuuuu
属性,这是一个默认值元组,在没有传入参数值时使用。在调用函数时,您可以看到可变列表的变化,并且由于函数返回eggs
列表,因此您还可以看到它与该元组中的第二个值是完全相同的对象
如果您不希望共享默认值,而是需要在每次调用函数时为参数指定一个新值,但未指定参数,则需要将默认值设置为sentinel对象。如果您的参数仍然设置为函数体中的sentinel,则可以执行代码来设置新的默认值<代码>无通常是最佳选择:
def foo(bar='spam', eggs=None):
if eggs is None:
eggs = []
如果可以使用None
作为非默认值,请使用事先创建的单例sentinel:
_sentinel = object()
def foo(bar='spam', eggs=_sentinel):
if eggs is _sentinel:
eggs = []
函数只是python中的一个对象,它是使用
def
语法创建的。定义函数时,默认值存储在函数对象中,以后不会重新计算
这有时用于创建保存到后续调用的函数变量。您可以使用\uuuu defaults\uuuu
方法检查函数的默认值
初始化新对象而不是重用新对象的常用方法是:
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
您可以查看更多详细信息。您定义的函数本身就是一个对象。定义默认值时,这些默认值将绑定到已创建的函数 您可以看到这一点:
>>> def f(a, L=[]):
... L.append(a)
... return L
>>> print id(f)
4419902952
>>> print f.__defaults__
([],)
>>> f(1)
[1]
>>> print id(f)
4419902952
>>> print f.__defaults__
([1],)
进一步编辑,您可以看到列表容器不会更改:
>>> print id(f.__defaults__[0])
4419887544
>>> f(2)
[1, 2]
>>> print id(f.__defaults__[0])
4419887544
在随后的每次调用中,
f
函数的默认列表(“L
”)将附加a
值。对不起,这个答案是针对不同的问题的,但是如果有人想看它,我会把它留在这里作为参考。定义一次意味着在执行代码的第一个点,默认变量被分配给一个对象,该对象保留在函数对象本身中
请注意,仅打印1个对象地址,使用默认列表对象
def f(a, L=[]):
print("id default: ", id(L))
L.append(a)
print("id used: ", id(L)
return L
注意,打印了两个不同的对象地址,当您在函数中执行L=[]时,您将L绑定到不同的列表对象,因此默认列表对象不会得到更改
def f(a, L=[]):
print("id default: ", id(L))
if L == []:
L = []
L.append(a)
print("id used: ", id(L))
return L
上面的函数与下面的函数基本相同,只是它使用None对象而不是空的list对象
def f(a, L=None):
print("id default", id(L))
if L is None:
L = []
L.append(a)
print("id used: ", id(L))
return L
不是“第一次调用时”,而是“定义时”。密切相关,但不是重复:这与工作环境无关。这是关于何时计算函数默认值的问题。你是对的,我误解了这个问题,但是,添加一种获得所需行为的方法通常是有用的。当然,但这就是目的;e、 g.这篇文章最初是作为一个复制品结束的。如果你现在看到这个问题,它已经链接了教程的相关部分(也有解决方案)。这个答案需要解释