В Python я могу указать аргумент функции по умолчанию с точки зрения других аргументов?

Предположим, у меня есть функция Python, которая принимает два аргумента, но я хочу, чтобы второй аргумент был необязательным, а значение по умолчанию было передано в качестве первого аргумента. Итак, я хочу сделать что-то вроде этого:

def myfunc(arg1, arg2=arg1):
    print (arg1, arg2)

За исключением того, что это не работает. Единственное обходное решение, о котором я могу думать, это:

def myfunc(arg1, arg2=None):
    if arg2 is None:
        arg2 = arg1
    print (arg1, arg2)

Есть лучший способ сделать это?


person Ryan C. Thompson    schedule 01.01.2011    source источник
comment
Я просто переосмысливаю это, возможно, это можно сделать с помощью декоратора. На первый взгляд будет неясно, что он делает, так что, вероятно, это плохая идея, но это идея.   -  person moinudin    schedule 01.01.2011
comment
Не прямо в строке заголовка функции, нет. Но внутри тела функции, проверив if argn is None: argn = <default_expression_involving_other_args>, да.   -  person smci    schedule 18.07.2019


Ответы (3)


Как говорит @Ignacio, вы не можете этого сделать. В вашем последнем примере может возникнуть ситуация, когда None является допустимым значением для arg2. Если это так, вы можете использовать дозорное значение:

sentinel = object()
def myfunc(arg1, arg2=sentinel):
    if arg2 is sentinel:
        arg2 = arg1
    print (arg1, arg2)

myfunc("foo")           # Prints 'foo foo'
myfunc("foo", None)     # Prints 'foo None'
person moinudin    schedule 01.01.2011
comment
вероятно, лучше просто по умолчанию arg2 установить значение None и проверить это вместо того, чтобы возиться с настраиваемым объектом Sentinel, если вам не нужно обрабатывать предоставленный пользователем None отличается от значения по умолчанию - person user234461; 07.03.2018

Не совсем. Другие имена аргументов не существуют до тех пор, пока функция фактически не будет введена.

person Ignacio Vazquez-Abrams    schedule 01.01.2011
comment
Но вы можете немного исправить это, изменив предложение if в обходном пути на: arg2 = arg2 or arg1 - person Michael Dunn; 01.01.2011
comment
@Michael Майкл Это не удастся, если arg2 равно 0, False или пустой последовательности. - person moinudin; 01.01.2011

Второй способ, на мой взгляд, прекрасен: там точно понятно, что ты делаешь, и для всех тех, кто придет после тебя и будет читать код. Хотя при документировании поведения по умолчанию возникают небольшие накладные расходы, использование «Нет» или любого другого, чтобы ваша функция генерировала значение по умолчанию, очень распространено. На мой взгляд, включение логики в вызовы функций, безусловно, не похвально, очень скоро это может стать очень сложным. Так что просто оставьте его в теле функции, где и весь код.

person Inca    schedule 01.01.2011