Как указать, что функция должна использовать значение по умолчанию для необязательного аргумента, не опуская его?

Я пытаюсь написать код, который не повторяется, следуя принципу DRY.

Рассмотрим вызов функции с множеством аргументов, как обязательных, так и необязательных. В некоторых случаях я хотел бы указать значение для необязательного аргумента, тогда как в других случаях я хотел бы оставить это значение по умолчанию. Чтобы упростить мою проблему:

def func(a, b=2):
    print("b = {}".format(b))

avalue = 1
condition = 2
arg = None  # <-- Means: "use default" 
if condition == 1:
    arg = 3

func(avalue, b=arg)

Вывод:

b = None

Ожидаемый результат:

b = 2

Таким образом, я пытаюсь избежать двойного кодирования вызова функции следующим образом:

if arg:
    func(avalue, b=arg)
else:
    func(avalue)

Возможно ли это в Python?


person Håkon Hægland    schedule 26.06.2017    source источник


Ответы (5)


Используйте словарь и установите необязательный аргумент в виде пары ключ-значение только в том случае, если вы хотите его указать. Затем примените словарь, используя синтаксис вызова **kwargs:

avalue = 1
condition = 2

kwargs = {}
if condition == 1:
    kwargs['b'] = 3

func(avalue, **kwargs)

Пустой словарь (случай condition != 1) оставляет для b значение по умолчанию.

person Martijn Pieters    schedule 26.06.2017

Одним из решений может быть:

def func(a, b=2, **kwargs):
    print("b = {}".format(b))

avalue = 1
condition = 2

func(avalue, **{} if condition != 1 else {'b':3})
person be_good_do_good    schedule 26.06.2017

Что о :

def func(a, b=None):
    if not b:
        b = 2
    print("b = {}".format(b))

avalue = 1
condition = 2
arg = None  # <-- Means: "use default" 
if condition == 1:
    arg = 3

func(avalue, b=arg)

Однако на данный момент значение по умолчанию на самом деле не используется так, как должно быть, значения по умолчанию обычно сохраняются, когда у вас есть два разных метода, один из которых работает так, как другой не должен, например, для сложения/вычитания с помощью переключателя :

def maths(a,b,sub=false):
    result = a + b
    if sub:
        result = a - b
    return result
person Tomos Williams    schedule 26.06.2017
comment
Хорошее предложение, но я не могу изменить func, так как это библиотечная функция. - person Håkon Hægland; 26.06.2017

Как насчет этого:

def func(a, b=None):
    b = 2 if not b else b
    print("b = {}".format(b))

avalue = 1
condition = 2
arg = None  # <-- Means: "use default"
if condition == 1:
    arg = 3

func(avalue, arg)  # b = 2

а если condition = 1:

func(avalue, arg)  #  b = 3

Вышеприведенное предполагает, что вы можете изменить определение функции. Если это не так, вы должны пойти с **kwargs.

person Ma0    schedule 26.06.2017
comment
В большинстве случаев я бы предпочел это трюку **kwargs. Материал в stdlib делает это. хотя с if b is None: b = 2 - person ; 26.06.2017

Оп упомянул, что функция func не может быть изменена, поэтому мое предложение будет следующим:

def func(a, b=2):
    print("b = {}".format(b))

avalue = 1
condition = 2
if condition == 1:
    func(avalue, b=3)
else:
    func(avalue)
person Tomos Williams    schedule 26.06.2017