我想很多人都看过python的函数接收默认参数。例如:
def foo(a=[]):
a.append(3)
return a
如果我们使用foo()调用此函数,则每次调用后输出都会附加整数“3”。
定义此函数时,在当前环境中定义名为“foo”的函数对象,此时还会计算默认参数值。每次在没有参数的情况下调用函数时,将根据代码更改评估的参数值。
我的问题是,此评估参数在哪里? 是在函数对象中还是在调用函数时它在方法对象中? 由于python中的所有内容都是一个对象,因此必须有一些位置来保存'a' - > evaluate参数的name->值绑定。我是否过度思考这个问题?
答案 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
这是不同版本的问题吗?