7

我刚开始学习 python,只是被默认参数概念所震撼。

在python doc中提到,函数的默认参数值仅在def遇到语句时计算一次。这使得不可变和可变默认函数参数的值之间存在很大差异。

>>> def func(a,L=[]):
      L.append(a)
      return L
>>> print(func(1))
[1]
>>> print(func(2))
[1, 2]

这里可变函数参数 L 保留最后分配的值(因为默认值不是在函数调用期间计算的,就像在 C 中一样)

python中默认参数值的生命周期是程序的生命周期(如C中的静态变量)?

编辑 :

>>> Lt = ['a','b']
>>> print(func(3,Lt))
['a', 'b', 3]
>>> print(func(4))
[1, 2, 4]

这里在函数调用期间保留func(3,Lt)默认值,L不会被Lt.

那么默认参数有两个内存吗?一个用于实际默认值(具有程序范围),另一个用于将对象传递给它时(具有函数调用范围)?

4

2 回答 2

13

由于参数是函数对象的属性,它通常与函数具有相同的生命周期。通常,函数从加载模块的那一刻起就存在,直到解释器退出。

但是,Python 函数是一等对象,您可以提前删除对函数的所有引用(动态)。然后垃圾收集器可能会获取该函数以及随后的默认参数:

>>> def foo(bar, spam=[]):
...     spam.append(bar)
...     print(spam)
... 
>>> foo
<function foo at 0x1088b9d70>
>>> foo('Monty')
['Monty']
>>> foo('Python')
['Monty', 'Python']
>>> foo.func_defaults
(['Monty', 'Python'],)
>>> del foo
>>> foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

请注意,您可以直接访问可写的func_defaults属性(__defaults__在 python 3 中),因此您可以通过重新分配给该属性来清除默认值。

于 2013-05-14T18:08:16.997 回答
3

它至少与函数对象具有相同的生命周期(没有一些时髦的东西)。因此,如果加载它的模块被所有其他模块卸载,并且没有其他引用,那么函数对象及其成员可能会被销毁。

因为 Python 是垃圾收集器,所以您实际上不需要担心这一点。如果对象逃逸,并且程序的其他部分有引用,它就会挂起。

如果您的观点是您希望依赖挂在周围的对象而不是被重置,那么是的,您可以这样做,除非您有一些时髦的卸载模块,或者如果您有一些代码分配给函数对象上的变量存储默认值。

于 2013-05-14T18:03:52.817 回答