Питоновское решение для условных аргументов
У меня есть функция с двумя необязательными параметрами:
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: ''