ленивая оценка в Python3 - PullRequest
       6

ленивая оценка в Python3

3 голосов
/ 03 февраля 2020

Предположим, у меня есть функция с побочными эффектами (в этом примере побочный эффект заключается в том, что что-то напечатано). Существует ли какая-либо версия any () или какая-либо конструкция итеративного списка, которая НЕ будет вызывать побочные эффекты после нахождения истинного результата?

Например, предположим, что эта функция:

def a(x):
   print("A function got: " + str(x))
   return x == 2

Можно было бы надеяться , что этот вызов поможет. Конечно, он не:

any([
  a(i) for i in range(5)
])

Какие отпечатки:

A function got: 0
A function got: 1
A function got: 2
A function got: 3
A function got: 4

Но я бы хотел напечатать это вместо:

A function got: 0
A function got: 1
A function got: 2

Почему? Range является итерируемым, понимание списка создает итерируемое, я бы ожидал, что Python объединит их в цепочку и прекратит выполнение целиком, как только функция any () перестанет потреблять, что она должна сделать, как только достигнет Первый Истинный.

Что я неправильно понимаю? Какая версия этого будет вести себя таким образом, если таковая имеется?

Ответы [ 4 ]

4 голосов
/ 03 февраля 2020

Всякий раз, когда вы используете список, все значения оцениваются. Единственный способ получить ленивую оценку - сохранить ее в качестве итератора. Вы можете сделать это с пониманием генератора:

any(a(i) for i in range(5))

Для ясности, использование скобок - это то же самое, что и any(list(a(i) for i in range(5))).

1 голос
/ 03 февраля 2020

Вы также можете просто запустить l oop и break из него:

for i in range(5):
    if a(i):
        break

Итак

def my_any(func, it):
    for i in it:
        if func(i):
            break

my_any(a, range(5))
0 голосов
/ 03 февраля 2020

еще одно правильное решение: сначала импортируйте из itertool, затем

l=list(takewhile(lambda x:a(x) is False, range(5)))
0 голосов
/ 03 февраля 2020

Вы можете использовать приведенный ниже код, добавив условие в ваше понимание списка

def a(x):
   print("A function got: " + str(x))

any([
  a(i) for i in range(5) if i<3 
])
...