Насколько я понимаю, когда Python анализирует исходный код функции, он компилирует его в байт-код, но не запускает этот байт-код до вызова функции (поэтому недопустимые имена переменных в функциях не вызывают исключение, если вы не вызываете функцию ).
Аргументы по умолчанию не создаются во время первоначальной настройки функции, а только при первом вызове функции, независимо от того, предоставлены аргументы или нет. Этот же экземпляр аргумента по умолчанию используется для всех будущих вызовов, что можно увидеть, используя изменяемый тип в качестве аргумента по умолчанию.
Однако если мы поместим функцию внутрь другой функции, аргумент по умолчанию теперь будет повторно создаваться каждый раз при вызове внешней функции, как показано в следующем коде:
def f(x):
def g(y, a=[]):
a.append(y)
return a
for y in range(x, x + 2):
print('calling g from f:', g(y))
return g(y + 1)
for x in range(2):
print('calling f from module scope:', f(x))
Это распечатывает
calling g from f: [0]
calling g from f: [0, 1]
calling f from module scope: [0, 1, 2]
calling g from f: [1]
calling g from f: [1, 2]
calling f from module scope: [1, 2, 3]
Означает ли это, что каждый раз, когда вызывается f
, байт-код g
перестраивается? Такое поведение кажется ненужным и странным, поскольку байт-код f
(включая g
?) создается только один раз. Или, возможно, это только аргумент по умолчанию g
, который повторно создается при каждом вызове f
?