Say there's a kind of function that returns either some value or None
, and we have three such functions: egg
, ham
and spam
.
假设有一种函数返回某个值或None,我们有三个这样的函数:egg,ham和spam。
The goal is to call egg
, ham
, spam
and return the first non-None value returned, and if there's no valid value return, return None
.
目标是调用egg,ham,spam并返回返回的第一个非None值,如果没有有效值返回,则返回None。
The most straightforward way would be:
最直接的方式是:
def func():
ret = egg()
if ret:
return ret
ret = ham()
if ret:
return ret
ret = spam()
if ret:
return ret
return None
or, a smarter but maybe harder to read solution is:
或者,更聪明但可能更难阅读的解决方案是:
def func():
return egg() or ham() or spam()
Here're my questions (there could be more than three candidate functions to call):
这是我的问题(可能有三个以上的候选函数要调用):
- Is the second way hard to read and should be avoided?
- Is there a better way to design such control flow? I remember there's something in Lisp that does exactly this, but what about in Python?
第二种方式难以阅读且应该避免吗?
有没有更好的方法来设计这样的控制流程?我记得在Lisp中有一些东西可以做到这一点,但在Python中呢?
2 个解决方案
#1
0
Something like:
def sifter():
funcs = [eggs, ham, spam]
result = None
while funcs and result is None:
result = funcs.pop(0)()
return result
A little explanation: assuming, as in the question, that all the functions to run accept no arguments the while funcs and result is None
bit ensures there are more functions to try and that the current result is still None. in the while loop we:
一个小解释:假设,如问题所示,所有要运行的函数都不接受参数,而funcs和结果是None位确保有更多的函数要尝试,并且当前结果仍然是None。在while循环中我们:
- Pop the first item from the list of funcs
funcs.pop(0)
. (The list of funcs then looses that func) - call the poped function
()
- Assign what is returned from the function call to the name
result =
弹出funcs funcs.pop(0)列表中的第一项。 (函数列表然后失去那个函数)
调用poped函数()
将函数调用返回的内容分配给名称result =
Ready for the next loop through the while statement.
准备好通过while语句进行下一个循环。
#2
0
As this requirement is very similar to the builtin any()
I would write:
因为这个要求非常类似于内置的any()我会写:
def anyval(iterable):
r = None
for r in iterable:
if callable(r):
r = r()
if r != None:
break
return r
def foo():
return None
def bar():
return 0
def baz(x):
return x * 3.14
print(anyval([None,foo,bar]))
print(anyval([None,lambda: baz(3.14)]))
#1
0
Something like:
def sifter():
funcs = [eggs, ham, spam]
result = None
while funcs and result is None:
result = funcs.pop(0)()
return result
A little explanation: assuming, as in the question, that all the functions to run accept no arguments the while funcs and result is None
bit ensures there are more functions to try and that the current result is still None. in the while loop we:
一个小解释:假设,如问题所示,所有要运行的函数都不接受参数,而funcs和结果是None位确保有更多的函数要尝试,并且当前结果仍然是None。在while循环中我们:
- Pop the first item from the list of funcs
funcs.pop(0)
. (The list of funcs then looses that func) - call the poped function
()
- Assign what is returned from the function call to the name
result =
弹出funcs funcs.pop(0)列表中的第一项。 (函数列表然后失去那个函数)
调用poped函数()
将函数调用返回的内容分配给名称result =
Ready for the next loop through the while statement.
准备好通过while语句进行下一个循环。
#2
0
As this requirement is very similar to the builtin any()
I would write:
因为这个要求非常类似于内置的any()我会写:
def anyval(iterable):
r = None
for r in iterable:
if callable(r):
r = r()
if r != None:
break
return r
def foo():
return None
def bar():
return 0
def baz(x):
return x * 3.14
print(anyval([None,foo,bar]))
print(anyval([None,lambda: baz(3.14)]))