Питоновское решение для условных аргументов

У меня есть функция с двумя необязательными параметрами:

def func(a=0, b=10):
    return a+b

Где-то в моем коде я делаю некоторый условный аргумент, проходящий как:

if a and b:
   return func(a, b)
elif a:
   return func(a)
elif b:
   return func(b=b)
else:
   return func()

Есть ли способ упростить код в этом шаблоне?

ИЗМЕНИТЬ

Предположим, что я не разрешен реализовывать логику параметров по умолчанию внутри func.

У меня может быть несколько функций типа func: func1, func2 и func3 будут содержать

a = a or 0
b = b or 10

заявления.

Но я вызываю эти серии функций для устранения дублирования. (с использованием декоратора)

Ответ 1

Если вы не хотите что-либо менять в func, тогда разумный вариант будет передавать аргумент функции:

>>> def func(a=0,b=10):
...  return a+b
...
>>> args = {'a':15,'b':15}
>>> func(**args)
30
>>> args={'a':15}
>>> func(**args)
25
>>> args={'b':6}
>>> func(**args)
6
>>> args = {}
>>> func(**args)
10

или просто:

>>>func(**{'a':7})
17

Ответ 2

Почему бы не передать эту логику функции?

def func(a, b):
    a = a or 0
    b = b or 10
    return a + b

Ответ 3

чтобы решить ваш конкретный вопрос, я бы сделал:

args = {'a' : a, 'b' : b}
for varName, varVal in args.items():
    if not varVal:
        del args[varName]
f(**args)

Но самым питоническим способом было бы использовать None в качестве значения по умолчанию в вашей функции:

f(a=None, b=None):
    a = 10 if a is None else a
    ...

и просто позвоните f(a, b)

Ответ 4

Переход по теперь удаленным комментариям к вопросу о том, что проверка предназначена для того, чтобы переменные были None, а не были ложными, измените func так, чтобы они обрабатывали аргументы None:

def func(a=None, b=None):
   if a is None:
      a = 0
   if b is None:
      b = 10

И затем просто вызывайте func(a, b) каждый раз.

Ответ 5

По умолчанию все методы в Python принимают аргументы переменной.

Когда вы определяете аргумент в сигнатуре метода, вы явно требуете его. В вашем фрагменте то, что вы делаете, дает ему значение по умолчанию - не делает его необязательным.

Рассмотрим следующее:

>>> def func(a,b):
...    a = a if a else 0
...    b = b if b else 10
...    return a+b
...
>>> a = b = None
>>> func(a,b)
10
>>> a = 5
>>> b = 2
>>> func(a,b)
7
>>> func()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() takes exactly 2 arguments (0 given)

В этом фрагменте требуются как a, так и b, так как я не определял значения по умолчанию. Они не являются необязательными.

Однако в вашем фрагменте, поскольку вы указали им значения по умолчанию в сигнатуре метода, они выглядят как необязательные, но на самом деле у них просто назначены значения по умолчанию.

>>> def func(a=0,b=10):
...    return a+b
...
>>> func()
10

Вы можете подтвердить это, проверив список аргументов внутри тела метода:

>>> def func(a=b,b=10):
...    print locals().keys()
...
>>> func()
['a', 'b']

Один из способов заставить вашу функцию принимать любое количество аргументов (другими словами, делая их все необязательными):

>>> def func(*args,**kwargs):
...    print len(args),args
...    print len(kwargs),kwargs
...
>>> func("hello","world",a=5,b=10)
2 ('hello', 'world')
2 {'a': 5, 'b': 10}
>>> func()
0 ()
0 {}
>>> func(1,2)
2 (1, 2)
0 {}
>>> func(a)
1 (5,)
0 {}
>>> func(foo="hello")
0 ()
1 {'foo': 'hello'}

Ответ 6

Вы можете добавить декоратор, который бы устранил аргументы None:

def skip_nones(fun):
    def _(*args, **kwargs):
        for a, v in zip(fun.__code__.co_varnames, args):
            if v is not None:
                kwargs[a] = v
        return fun(**kwargs)
    return _

@skip_nones
def func(a=10, b=20):
    print a, b

func(None, None) # 10 20
func(11, None)   # 11 20
func(None, 33)   # 10 33

Ответ 7

Чтобы ответить на ваш личный вопрос:

func(a or 0, b or 10) 

Edit: См. Комментарий, почему это не отвечает на вопрос.

Ответ 8

Это может сработать:

def f(**kwargs):
    a = get(kwargs, 0)
    b = get(kwargs, 10)
    return a + b

Ответ 9

Вы можете использовать троичный оператор if-then для передачи условных аргументов в функции https://www.geeksforgeeks.org/ternary-operator-in-python/

Например, если вы хотите проверить, существует ли ключ на самом деле, перед его передачей вы можете сделать что-то вроде:

 
    def func(arg):
        print(arg)

    kwargs = {'name':'Adam')

    func( kwargs['name'] if 'name' in kwargs.keys() else '' )       #Expected Output: 'Adam'
    func( kwargs['notakey'] if 'notakey' in kwargs.keys() else '' ) #Expected Output: ''