Где параметр по умолчанию в функции Python
Я думаю, многие люди видели функцию python, которая получает параметры по умолчанию. Например:
def foo(a=[]):
a.append(3)
return a
Если мы будем называть эту функцию с помощью foo(), то после вызова будет добавлено целое число "3".
Когда эта функция определена, объект функции с именем "foo" определяется в текущей среде, а также значения параметров по умолчанию оцениваются в это время. Каждый раз, когда функция вызывается без параметра, значение оцененного параметра будет изменено в соответствии с кодом.
Мой вопрос: , где этот оцениваемый параметр существует?
Является ли он в объекте функции или находится в объекте метода при вызове функции?
Поскольку все в python является объектом, должно быть место для привязки имени- > значения параметра 'a' → оцененный. Я передумал эту проблему?
Ответы
Ответ 1
Как уже говорили другие, значения по умолчанию хранятся в объекте функции.
Например, в CPython вы можете сделать это:
>>> def f(a=[]):
... pass
...
>>> f.func_defaults
([],)
>>> f.func_code.co_varnames
('a',)
>>>
Тем не менее, co_varnames
может содержать больше имен аргументов, поэтому требуется дальнейшая обработка, и эти атрибуты могут даже отсутствовать в других реализациях Python. Поэтому вместо этого вы должны использовать модуль inspect
, который заботится обо всех деталях реализации для вас:
>>> import inspect
>>> spec = inspect.getargspec(f)
>>> spec
ArgSpec(args=['a'], varargs=None, keywords=None, defaults=([],))
>>>
ArgSpec
- это именованный кортеж, поэтому вы можете получить доступ ко всем значениям в качестве атрибутов:
>>> spec.args
['a']
>>> spec.defaults
([],)
>>>
Как сообщает документация, кортеж defaults
всегда соответствует n последним аргументам из args
. Это дает вам ваше отображение.
Чтобы создать dict, вы можете сделать это:
>>> dict(zip(spec.args[-len(spec.defaults):], spec.defaults))
{'a': []}
>>>
Ответ 2
Он привязан к объекту функции, см. 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': []}
(Но, по-видимому, версия яков лучше.)
Ответ 3
В объекте функции в func_defaults
:
def f(a=[]): a.append(3)
print f.func_defaults # ([],)
f()
print f.func_defaults # ([3],)
Ответ 4
Он сохраняется в атрибуте func_defaults
объекта функции.
>>> foo.func_defaults
([],)
>>> foo()
([3],)
Ответ 5
Я нашел интересную ситуацию: в версии 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
Это проблема разных версий?