调用函数列表的大多数pythonic方法

时间:2019-10-24 20:56:48

标签: python python-3.x

我有一个功能列表,如下所示:

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的建议。在每个函数都返回某个值的更一般的情况下,我想使用上一个函数的返回值(无论它是什么)来决定是否运行下一个函数?每个函数可能还需要以前函数的某些返回值作为参数。

3 个答案:

答案 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)),
]