Например, при
def expensive_call(x):
print(x)
if x == "d":
return x
def expensive_call_2(x, y):
print(x)
print(y)
return x + y
a = [expensive_call("a"), expensive_call_2("b", "c"), expensive_call("d")]
next((e for e in a if e is not None), 'All are Nones')
вывод равен
a
b
c
d
Out[22]: 'bc'
Поскольку expensive_call("d")
оценивается с нетерпением, обратите внимание, что «d» выводится даже при вызове next
короткие замыкания при втором вызове с выводом «bc».
Я жестко кодирую вызовы в списке a
, и a
не обязательно должна быть структурой данных списка.
Одно из возможных решений заключается в следующем:
a = ['expensive_call("a")', 'expensive_call_2("b", "c")', 'expensive_call("d")']
def generator():
for e in a:
r = eval(e)
if r is not None:
yield r
next(generator(), 'All are Nones')
Выходное значение равно
a
b
c
Out[23]: 'bc'
по желанию. Однако мне не очень нравится использовать eval. Я также предпочел бы не использовать какое-либо решение, которое изначально хранит указатель на функцию и аргументы отдельно, как (expensive_call, ("a"))
. В идеале я хотел бы иметь что-то вроде
a = lazy_magic([expensive_call("a"), expensive_call_2("b", "c"), expensive_call("d")])
next((e for e in a if e is not None), 'All are Nones')
Обратите внимание, что https://stackoverflow.com/a/3405828/2750819 - аналогичный вопрос, но он применяется только в том случае, если функции имеют одинаковую сигнатуру метода.