Как правильно задать новую пустую коллекцию в качестве параметра по-умолчанию для функции
Во время решения задачи появилась потребность каждый раз при создании функции обновлять параметр arg
дефолтным значением dict()
В процессе решения задачи для меня подобная запись показалась вполне логичной:
def arbitrary(arg = dict()):
return arg
a = arbitrary()
b = arbitrary()
print(a is b) # True
Однако, как ни странно, при такой записи в arg
каждый раз присваивается ссылка на один и тот же словарь.
Далее последовала следующая запись (уже отвечает требованию):
def arbitrary(arg = None):
if not arg:
arg = dict()
return arg
a = arbitrary()
b = arbitrary()
print(a is b) # False
Есть ли какой-нибудь более лаконичный или общепринятый способ записи для этого случая?
UPD: Важное уточнение, пустой словарь должен присваиваться переменной arg
на этапе её объявления, либо в самом верху функции. Пример из вопроса - код, ужатый до "воспроизводимой проблемы".
Ответы (2 шт):
Можно так записать:
def arbitrary(arg = None):
return arg or dict()
В Python, параметры по умолчанию вычисляются один раз при определении функции - так что это самый оптимальный вариант:
def arbitrary(arg = dict()):
return arg or dict()
a = arbitrary()
b = arbitrary()
print(a is b) # False
print(a, b) # {} {}
Но если он вам не подходит..
Можно немного поиздеваться над функцией:
def arbitrary(arg = dict()):
return arg
a = arbitrary()
b = arbitrary()
print(a is b) # True
# Переопределяем параметр по умолчанию перед вызовом функции
a = arbitrary()
arbitrary.__defaults__ = (dict(),)
b = arbitrary()
print(a is b) # False
print(a, b) # {} {}
Но в таком случае уже проще декоратор навесить:
def update_default_dict(func):
def wrapper(*args, **kwargs):
func.__defaults__ = (dict(),)
return func(*args, **kwargs)
return wrapper
@update_default_dict
def arbitrary(arg=dict()):
return arg
a = arbitrary()
b = arbitrary()
print(a is b) # False
print(a, b) # {} {}