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


当前回答

如果你需要Python 3.8,你可以使用“赋值表达式”的新特性来减少If -else链的重复:

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

其他回答

根据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

这避免了:

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

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

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

实际上与timgeb的答案相同,但你可以使用括号来更好地格式化:

def check_all_the_things():
    return (
        one()
        or two()
        or five()
        or three()
        or None
    )

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

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

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

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

你可以使用循环:

conditions = (check_size, check_color, check_tone, check_flavor)
for condition in conditions:
    result = condition()
    if result:
        return result

这样做还有一个额外的好处,那就是您现在可以使条件的数量可变。

你可以使用map() + filter() (Python 3版本,使用Python 2中的future_builtins版本)来获得第一个这样的匹配值:

try:
    # Python 2
    from future_builtins import map, filter
except ImportError:
    # Python 3
    pass

conditions = (check_size, check_color, check_tone, check_flavor)
return next(filter(None, map(lambda f: f(), conditions)), None)

但这是否更具可读性还有待商榷。

另一种选择是使用生成器表达式:

conditions = (check_size, check_color, check_tone, check_flavor)
checks = (condition() for condition in conditions)
return next((check for check in checks if check), None)

或者使用max:

def check_all_conditions():
    return max(check_size(), check_color(), check_tone(), check_flavor()) or None