我有一个功能列表,如下所示:
def foo(a, b):
# do stuff
return True # or False
def bar(c):
# do stuff
return False # or True
def baz(d, e, f):
# do stuff
return True # or False
我想依次调用它们中的每一个,并且只有前一个返回True
时才继续进行下一个,就像这样:
if foo(1, 2):
if bar(3):
if baz(4, 5, 6):
print("Success!")
现在,我知道如果我所有的函数都接受相同的参数,那么我可以执行以下操作:
steps = [foo, bar, baz]
if all(func(*args) for func in steps):
print("Success!")
因为all
一旦达到返回值False
就会短路。但是,它们并不都接受相同的参数。
最干净的方法是什么?
编辑:感谢您提供有关压缩args的建议。在每个函数都返回某个值的更一般的情况下,我想使用上一个函数的返回值(无论它是什么)来决定是否运行下一个函数?每个函数可能还需要以前函数的某些返回值作为参数。
答案 0 :(得分:6)
and
运算符也会短路,因此您可以执行以下操作:
if foo(1, 2) and bar(3) and baz(4, 5, 6):
print("Success")
如果您想要更一般的方法,可以列出一个lambda。
steps = [
lambda: foo(1, 2),
lambda: bar(3),
lambda: baz(4, 5, 6)
]
if all(f() for f in steps):
print("Success")
或元组列表:
steps = [
(foo, (1, 2)),
(bar, (3)),
(baz, (4, 5, 6))
]
if all(f(*args) for f, args in steps):
print("Success")
答案 1 :(得分:3)
像这样使用all
:
steps = [foo, bar, baz]
arguments = [[1, 2], [3], [4, 5, 6]]
if all(func(*args) for func, args in zip(steps, arguments)):
print("Success!")
答案 2 :(得分:3)
函数是可哈希对象,因此您可以将它们用作字典的键。
funcs = {
foo: (1, 2),
bar: (3,),
baz: (4, 5, 6),
}
这比单独的函数和参数列表要干净一些,因为它可以防止列表不同步。
现在只需使用all
:
if all(f(*args) for f, args in funcs.items()):
print("Success!")
在最新版本的Python(3.8.0)和先前的次要版本(3.7.x)中订购字典。如果您使用的是该语言的旧版本(<3.7),则仍然可以使用collections.OrderedDict
进行同样的操作。
如果您想多次调用同一个函数,则此方法不起作用,因为字典键必须唯一。在这种情况下,您应该使用配对列表:
steps = [
(foo, (1, 2)),
(bar, (3,)),
(baz, (4, 5, 6)),
(foo, (7, 8)),
]