Где живет изменяемый объектный аргумент функции? Есть ли таблица символов? (учебник по Python 4.7.1)

Прохождение учебника по Python в разделе 4.7.1 где-то хранится изменяемый аргумент по умолчанию, но я не могу найти его, используя dir(), globals(), locals() или f.__dict__. Я имею в виду этот код:

def f(a, L=[]):
    L.append(a)
    return L

ведет себя как:

>>> print(f(1))
[1]
>>> print(f(2))
[1, 2]
>>> print(f(3))
[1, 2, 3]

Я ожидал бы увидеть это в пространстве имен функции, скажем, когда я делаю dir(f), но его там нет.

Я просмотрел это, но это намного больше, чем я, вероятно, ищу .


person user3325563    schedule 19.09.2018    source источник
comment
Почему вы хотите это знать (потому что вам вообще не следует этого делать)?   -  person martineau    schedule 19.09.2018
comment
... это в f.__defaults__, только что видел   -  person user3325563    schedule 19.09.2018
comment
@martineau да, это чистое любопытство и желание немного разобраться во внутренностях языка   -  person user3325563    schedule 19.09.2018
comment
Обратите внимание, что f.__defaults__ доступен только для доступа к значениям по умолчанию. Различные реализации Python сохраняют значения функций по умолчанию в оптимизированных структурах данных.   -  person MisterMiyagi    schedule 19.09.2018


Ответы (3)


В соответствии с моделью данных Python:

__defaults__ Кортеж, содержащий значения аргументов по умолчанию для тех аргументов, которые имеют значения по умолчанию, или None, если ни один из аргументов не имеет значения по умолчанию.

>>> def foo(a=[]):
...    a.append(1)
...
... foo()
... foo.__defaults__
([1],)

Существует также __kwdefaults__ для аргументов, состоящих только из ключевых слов.

>>> def foo(a=1, *, b=2):
...     pass
...
... foo.__defaults__, foo.__kwdefaults__
((1,), {'b': 2})

Обратите внимание, что вещи в Python не обязательно хранятся в любом доступном месте. Например, счетчик ссылок объекта недоступен в качестве атрибута. Он существует только на уровне C реализации CPython и требует встроенная магия для доступа.

На самом деле, __defaults__ тоже не является "настоящим" атрибутом. Это встроенное свойство, извлекающее значения по умолчанию из любого места, где их хранит реализация.

# python3
>>> type(foo).__defaults__
<attribute '__defaults__' of 'function' objects>
# pypy3
>>>> type(foo).__defaults__
<getset_descriptor object at 0x00000001110adc98>
person MisterMiyagi    schedule 19.09.2018

It's in f.__defaults__:

>>> def f(a, L=[]):
...     L.append(a)
...     return L
...
>>> f.__defaults__
([],)

Вы не нашли __defaults__ в __dict__, потому что оно не хранится в __dict__; он хранится в выделенном члене структуры уровня C, который сопоставляется с атрибутом __defaults__ дескриптором типа функции.

person user2357112 supports Monica    schedule 19.09.2018
comment
Или __kwdefaults__, если это только квт. - person wim; 19.09.2018

Если вы используете Spyder, при вводе f. должны появиться параметры автозаполнения. Один из них — __defaults__, который содержит значения по умолчанию.

person Acccumulation    schedule 19.09.2018