我有一个方法,按顺序调用其他4个方法来检查特定的条件,并立即返回(不检查以下那些)每当一个返回一些真理。

def check_all_conditions():
    x = check_size()
    if x:
        return x

    x = check_color()
    if x:
        return x

    x = check_tone()
    if x:
        return x

    x = check_flavor()
    if x:
        return x
    return None

这似乎是一大堆行李规定。而不是每个2行if语句,我宁愿这样做:

x and return x

但这是无效的Python。我是不是错过了一个简单、优雅的解决方案?顺便说一句,在这种情况下,这四个检查方法可能代价很高,所以我不想多次调用它们。


当前回答

我很惊讶没有人提到内置的任何是为了这个目的:

def check_all_conditions():
    return any([
        check_size(),
        check_color(),
        check_tone(),
        check_flavor()
    ])

注意,尽管这个实现可能是最清晰的,但它计算所有的检查,即使第一个检查为True。


如果你真的需要在第一次检查失败时停止,考虑使用reduce来将一个列表转换为一个简单的值:

def check_all_conditions():
    checks = [check_size, check_color, check_tone, check_flavor]
    return reduce(lambda a, f: a or f(), checks, False)

reduce(function, iterable[, initializer]):应用2的函数 参数从左到右累加到iterable的项, 从而将可迭代对象减少为单个值。左边的参数x, 累积值和正确的参数y是否更新 值。如果存在可选初始化式,则为 在计算中置于可迭代对象的项之前

在你的情况下:

lambda a, f: a或f()是检查累加器a或当前检查f()是否为True的函数。注意,如果a为True, f()将不会被求值。 检查包含检查函数(来自lambda的f项) False是初始值,否则不会发生检查,结果总是True

Any和reduce是函数式编程的基本工具。我强烈建议你训练这些以及地图,这是很棒的!

其他回答

不要改变它

还有其他的方法来做这个,正如各种其他的答案所显示的。没有一个像原始代码那样清晰。

如果你想要相同的代码结构,你可以使用三元语句!

def check_all_conditions():
    x = check_size()
    x = x if x else check_color()
    x = x if x else check_tone()
    x = x if x else check_flavor()

    return x if x else None

我觉得这看起来很清晰。

演示:

python的方法是使用reduce(有人已经提到过)或itertools(如下所示),但在我看来,简单地使用或操作符的短路可以产生更清晰的代码

from itertools import imap, dropwhile

def check_all_conditions():
    conditions = (check_size,\
        check_color,\
        check_tone,\
        check_flavor)
    results_gen = dropwhile(lambda x:not x, imap(lambda check:check(), conditions))
    try:
        return results_gen.next()
    except StopIteration:
        return None

你是否考虑过只写if x: return x all in一行?

def check_all_conditions():
    x = check_size()
    if x: return x

    x = check_color()
    if x: return x

    x = check_tone()
    if x: return x

    x = check_flavor()
    if x: return x

    return None

这并没有比你所拥有的更少的重复性,但IMNSHO它读起来更流畅。

这是马丁第一个例子的一个变种。为了允许短路,它还使用了“可调用对象的集合”样式。

而不是循环,你可以使用内置的任何。

conditions = (check_size, check_color, check_tone, check_flavor)
return any(condition() for condition in conditions) 

注意,any返回一个布尔值,所以如果您需要检查的确切返回值,这个解决方案将不起作用。any将不会区分14,'red', 'sharp', 'spicy'作为返回值,它们都将作为True返回。