我有一个方法,按顺序调用其他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是函数式编程的基本工具。我强烈建议你训练这些以及地图,这是很棒的!
你可以使用循环:
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)