Python: передача условных параметров по имени

У меня есть куча функций, для некоторых из них требуется параметр bar, для некоторых из них требуется параметр foo, некоторые из них не требуют ни одного, а некоторые требуют обоих.

Я надеюсь вызывать все эти функции из одного и того же местоположения, поскольку функция ссылается на переменную.

Возможные решения, которые я нашел:

  1. function (bar = "some_value", foo = "другое значение")
  2. Используя проверку, а затем обнаружив, какие аргументы должны быть переданы в

Я не верю, что # 1 будет работать, но я знаю, что №2 будет. Есть ли у меня родной (не использующий библиотеку) способ сделать это?

В качестве примера:

functions = [lambda foo: foo.do_something(), lambda bar: bar.do_something_else(), lambda foo, bar: foo.something_with_bar(bar), lambda: do_another_task()
]
for function in functions: //call goes here

Примечание. На самом деле у меня есть много и много функций, которые я хочу вызвать с этими параметрами, и они не все хорошо хранятся в массиве. Я бы предпочел, чтобы я мог это сделать, не меняя самих функций.

2 ответа

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

foo = 'foo'
bar = 'bar'
if funcname == 'a': func = a # a takes no args
elif funcname == 'b': func = lambda: bb(bar=bar) # bb takes bar
elif funcname == 'c': func = lambda: ccc(foo=foo) # ccc takes foo
# call it, uniformly
func()

Аналогичный подход будет заключаться в "де-привязке":

if funcname == 'a': func = lambda foo, bar: a() # don't pass foo and bar
elif funcname == 'b': func = lambda foo, bar: bb(bar=bar) # don't pass foo
elif funcname == 'c': func = lambda foo, bar: ccc(foo=foo) # don't pass bar
# call it, uniformly
func(foo, bar)

Кроме того, если вы хотите реорганизовать свой код, чтобы сделать его более элегантным и объектно-ориентированным, определите интерфейс и реализации фасадов:

class FooBarInterface(object): def f(self, foo, bar): raise NotImplementedError
class A(FooBarInterface): def f(self, foo, bar): return a()
class B(FooBarInterface): def f(self, foo, bar): return bb(bar=bar)
class C(FooBarInterface): def f(self, foo, bar): return ccc(foo=foo)
if funcname == 'a': obj = A()
elif funcname == 'b': obj = B()
elif funcname == 'c': obj = C()
# call it, uniformly
obj.f()

И, пожалуйста, не используйте интроспекцию. Это сделает ваш код более сложным, чем нужно.


Никакой способ сделать это изначально, если вы не можете самостоятельно редактировать функции, если у вас есть

def func_a(**kwargs): foo = kwargs['foo'] # or even: foo = kwargs.get('foo', None) # in case foo wasn't passed the the function ...
def func_b(**kwargs): bar = kwargs.get('bar', None) ...

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

licensed under cc by-sa 3.0 with attribution.