我有一个方法,按顺序调用其他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。我是不是错过了一个简单、优雅的解决方案?顺便说一句,在这种情况下,这四个检查方法可能代价很高,所以我不想多次调用它们。


当前回答

不要改变它

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

其他回答

对我来说,最好的答案是@ phill -frost,然后是@wayne-werner's。

我发现有趣的是,没有人说过一个函数将返回许多不同的数据类型,这将强制检查x本身的类型来做任何进一步的工作。

所以我会将@PhilFrost的回答与保持单一类型的想法混合在一起:

def all_conditions(x):
    yield check_size(x)
    yield check_color(x)
    yield check_tone(x)
    yield check_flavor(x)

def assessed_x(x,func=all_conditions):
    for condition in func(x):
        if condition:
            return x
    return None

注意,x被作为一个参数传递,但all_conditions也被用作检查函数的传递生成器,其中所有检查函数都得到一个要检查的x,并返回True或False。通过使用带有all_conditions作为默认值的func,您可以使用assessed_x(x),或者您可以通过func传递进一步的个性化生成器。

这样,只要一个检查通过,您就会得到x,但它总是相同的类型。

根据Curly定律,你可以通过拆分两个关注点来提高代码的可读性:

我要检查哪些东西? 有一件事是真的吗?

分为两个功能:

def all_conditions():
    yield check_size()
    yield check_color()
    yield check_tone()
    yield check_flavor()

def check_all_conditions():
    for condition in all_conditions():
        if condition:
            return condition
    return None

这避免了:

复杂的逻辑结构 非常长的队伍 重复

...同时保留一个线性的,易于阅读的流。

根据您的特定情况,您可能还可以提出更好的函数名称,使其更具可读性。

理想情况下,我将重写check_函数以返回True或False而不是一个值。你的支票就变成了

if check_size(x):
    return x
#etc

假设你的x不是不可变的,你的函数仍然可以修改它(尽管他们不能重新分配它)-但是一个叫check的函数不应该真的修改它。

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

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

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

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

上面的Martijns的第一个例子略有变化,避免了循环中的if:

Status = None
for c in [check_size, check_color, check_tone, check_flavor]:
  Status = Status or c();
return Status