Питон:итерация по непустому списку без предложения if оказывается пустой.Почему?

StackOverflow https://stackoverflow.com/questions/703520

Вопрос

Как может итератор над непустой последовательностью без фильтрации и агрегации (sum(), и т. д.), ничего не дают?

Рассмотрим простой пример:

sequence = ['a', 'b', 'c']
list((el, ord(el)) for el in sequence)

Это дает [('a', 97), ('b', 98), ('c', 99)] как и ожидалось.

Теперь просто поменяйте местами ord(el) out для выражения, которое извлекает первое значение из некоторого генератора, используя (...).next() — простите за надуманный пример:

def odd_integers_up_to_length(str):
    return (x for x in xrange(len(str)) if x%2==1)

list((el, odd_integers_up_to_length(el).next()) for el in sequence)

Это дает [].Да, пустой список.Нет ('a',вещи) кортежи.Ничего.

Но мы не фильтруем, не агрегируем и не сокращаем.Генераторное выражение над n объекты без фильтрации или агрегации должны давать результат n объекты, да?Что происходит?

Это было полезно?

Решение

odd_integers_up_to_length(el).next() вызовет StopIteration, которая не перехватывается там, но перехватывается для выражения генератора внутри него, останавливая его, не давая ничего.

посмотрите на первую итерацию, когда значение равно «a»:

>>> odd_integers_up_to_length('a').next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Другие советы

Происходит следующее: next() звонок вызывает StopIteration исключение, которое поднимает стек к выражению внешнего генератора и останавливает что итерация.

А StopIteration это обычный способ итератора сигнализировать о завершении работы.Обычно мы этого не видим, потому что обычно next() вызов происходит внутри конструкции, которая использует итератор, например. for x in iterator или sum(iterator).Но когда мы звоним next() непосредственно, мы несем ответственность за поимку StopIteration.Если этого не сделать, возникает утечка в абстракции, что в данном случае приводит к неожиданному поведению во внешней итерации.

Урок, я полагаю:будьте осторожны с прямыми вызовами на next().

str — зарезервированное ключевое слово, вам следует назвать переменную по-другому.

Я также должен был дать совет о следующем

>>> seq=['a','b','c']
>>> list((el,4) for el in seq)
[('a',4), ('b',4), ('c',4)]

Так что это не list доставляю тебе здесь неприятности...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top