#python #function #jupyter #interpreter #definition
Вопрос:
Предположим, у меня есть функция Python foo
, которая принимает аргумент по умолчанию, где по умолчанию установлена некоторая глобальная переменная. Если я сейчас изменю эту глобальную переменную перед вызовом функции, аргумент по умолчанию по-прежнему будет иметь исходное значение этой глобальной переменной.
Например:
x = 1
def foo(a=x):
print a
x = 2
foo()
Это печатает 1
, а 2
не .
Как я должен писать свой код, чтобы я мог изменить эту глобальную переменную и обновить этот аргумент по умолчанию?
Комментарии:
1. Аргументы по умолчанию оцениваются только один раз…
Ответ №1:
Переменная по умолчанию вычисляется и устанавливается только один раз. Таким образом, Python создает копию ссылки, и с тех пор он всегда передает эту ссылку в качестве значения по умолчанию. Никакой переоценки не проводится.
Однако вы можете решить эту проблему, используя другой объект в качестве объекта по умолчанию, а затем используя if
оператор для его соответствующей замены. Что-то вроде:
the_default = object()
x = 1
def foo(a = the_default):
if a is the_default:
a = x
print a
x = 2
foo()
Обратите внимание, что мы используем is
для выполнения равенства ссылок. Поэтому мы проверяем, действительно ли это так default_object
. Вы не должны использовать the_default
объект где-то еще в своем коде.
Во многих кодах Python они используются None
по умолчанию (и, таким образом, уменьшают количество объектов конструкции). Например:
def foo(a = None):
if a is None:
a = x
print a
Однако обратите внимание, что если вы это сделаете, ваша программа не сможет провести различие между вызовом пользователя foo()
и foo(None)
использованием чего-либо, что the_object
затрудняет пользователю получение ссылки на этот объект. Это может быть полезно, если None
вы также являетесь действительным кандидатом: если вы хотите foo(None)
печатать 'None'
и нет x
.
Комментарии:
1. в качестве the_deault вы можете просто использовать «Нет», если только None не является допустимым значением для аргумента
2. @CarloLobrano: да. Я обновил ответ в тот же момент, когда вы написали этот комментарий. Единственная проблема может заключаться в том, что вы хотите исключить тот факт, что пользователи сами могут передавать этот объект. Используя что-то как
the_object
, вы более защищены от такого поведения.3. это верно. Иногда разумнее использовать «объекты по умолчанию», чем» Нет».