Определение аргумента по умолчанию в качестве глобальной переменной

#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. это верно. Иногда разумнее использовать «объекты по умолчанию», чем» Нет».