Python函数中的默认参数在哪里

时间:2012-04-12 09:32:25

标签: python

我想很多人都看过python的函数接收默认参数。例如:

def foo(a=[]):
    a.append(3)
    return a

如果我们使用foo()调用此函数,则每次调用后输出都会附加整数“3”。

定义此函数时,在当前环境中定义名为“foo”的函数对象,此时还会计算默认参数值。每次在没有参数的情况下调用函数时,将根据代码更改评估的参数值。

我的问题是,此评估参数在哪里? 是在函数对象中还是在调用函数时它在方法对象中? 由于python中的所有内容都是一个对象,因此必须有一些位置来保存'a' - > evaluate参数的name->值绑定。我是否过度思考这个问题?

5 个答案:

答案 0 :(得分:10)

正如其他人已经说过的那样,默认值存储在函数对象中。

例如,在CPython中你可以这样做:

>>> def f(a=[]):
...     pass
...
>>> f.func_defaults
([],)
>>> f.func_code.co_varnames
('a',)
>>>

但是,co_varnames可能包含多个args的名称,因此需要进一步处理,这些属性可能甚至不存在于其他Python实现中。因此,您应该使用inspect模块来代替您处理所有实现细节:

>>> import inspect
>>> spec = inspect.getargspec(f)
>>> spec
ArgSpec(args=['a'], varargs=None, keywords=None, defaults=([],))
>>>

ArgSpec是一个命名元组,因此您可以将所有值作为属性访问:

>>> spec.args
['a']
>>> spec.defaults
([],)
>>>

正如documentation所说,defaults元组始终对应于来自args的n个最后一个参数。这为您提供了映射。

要创建一个词典,你可以这样做:

>>> dict(zip(spec.args[-len(spec.defaults):], spec.defaults))
{'a': []}
>>>

答案 1 :(得分:4)

它附加到函数对象,请参阅foo.func_defaults

>>> foo()
>>> foo.func_defaults
([3],)
>>> foo()
>>> foo.func_defaults
([3, 3],)

如果您想要将a映射到[],您可以访问foo.func_code

defaults = foo.func_defaults
# the args are locals in the beginning:
args = foo.func_code.co_varnames[:foo.func_code.co_argcount] 
def_args = args[-len(defaults):]  # the args with defaults are in the end
print dict(zip(def_args, defaults)) # {'a': []}

(但是,显然,牦牛的版本更好。)

答案 2 :(得分:4)

它位于函数对象的func_defaults

def f(a=[]): a.append(3)

print f.func_defaults # ([],)

f()

print f.func_defaults # ([3],)

答案 3 :(得分:2)

它存储在函数对象的func_defaults属性中。

>>> foo.func_defaults
([],)
>>> foo()
([3],)

答案 4 :(得分:1)

我发现了一个有趣的情况:在python 2.5.2版本中,尝试函数'foo()'

>>> foo()
[1]
>>> foo()
[1]
>>> foo()
[1]

因为被调用函数的对象不同:

>>> id(foo())
4336826757314657360
>>> id(foo())
4336826757314657008
>>> id(foo())
4336826757314683160

在2.7.2版本中:

>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

在这种情况下,每次调用函数时对象都是相同的:

>>> id(foo())
29250192
>>> id(foo())
29250192
>>> id(foo())
29250192

这是不同版本的问题吗?