Что это за понимание?

#python-3.x #list-comprehension

#python-3.x #список-понимание

Вопрос:

Один из моих учеников обнаружил, что для ell (списка строк) и estr (строки) следующее True выражение равно, если член ell содержится в estr :

 any(t in estr for t in ell)
  

Кто-нибудь может объяснить, почему это синтаксически законно, и если да, то что генерирует понимание?

Комментарии:

1. (t in estr for t in ell) это выражение генератора, вы могли бы думать об этом как о «понимании генератора», хотя это не тот термин, который используется

Ответ №1:

Это выражение генератора.

 func_that_takes_any_iterable(i for i in iterable)
  

Это похоже на понимание списка, но это генератор, то есть он создает только один элемент за раз:

 >>> a = [i for i in range(10)]
>>> b = (i for i in range(10))
>>> print(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print(b)
<generator object <genexpr> at 0x7fb9113fae40>
>>> print(list(b))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print(list(b))
[]
  

При изолированном использовании выражения генератора круглые скобки требуются по синтаксическим соображениям. При создании в качестве аргумента функции синтаксис допускает отсутствие дополнительных круглых скобок.

Большинству функций все равно, какой тип итерации им задан — list , tuple, dict, generator и т. Д. — И генераторы вполне допустимы. Они также немного более эффективны с точки зрения памяти, чем понимание списков, поскольку они не генерируют все сразу. Для all() and any() это особенно хорошо, поскольку эти методы замыкаются, как только они возвращают False and True соответственно.


Начиная с python 3.8, синтаксические ограничения для оператора walrus := аналогичны — изолированно он должен использоваться внутри своего собственного набора круглых скобок, но внутри другого выражения его обычно можно использовать без них.

Комментарии:

1. Самое превосходное объяснение — очень четкое и полное. И во многих контекстах намного лучше, чем понимание списка, которое позже будет повторено.

2. «Они также немного более эффективны с точки зрения памяти , чем понимание списков, поскольку они не генерируют все сразу. Для all() и any() это особенно хорошо , поскольку эти методы замыкаются, как только они возвращают False и True соответственно. » Под «особенно хорошим», я полагаю, вы подразумеваете «значительно более экономичный по времени» 😉

Ответ №2:

Это синтаксически законно, потому что это не список. Любая форма (x для x в массиве) является генератором. Думайте об этом как о ленивом списке, который будет генерировать ответ только тогда, когда вы спросите.

Теперь генератор также является итеративным, поэтому вполне нормально, что он находится внутри функции any() .

 willBeTrue = any(True for i in range(20))

  

Таким образом, это в основном сгенерирует 20 истинных значений, и любая функция ищет любое истинное значение; таким образом, вернет True .

Теперь перейдем к вашему выражению:

 ans = any(t in estr for t in ell)
  

Это {t в estr} возвращает логическое значение. Теперь генератор делает len (ell) количеством этих логических значений, и любое из них кажется хорошим .. поскольку по крайней мере одно значение true, я возвращаю True.

Комментарии:

1. willBeTrue = any(True for i in range(20)) будет генерироваться только один True — после того any , как он будет статистизирован, и больше никаких истин не будет сгенерировано.