почему itertools.count () потребляет дополнительный элемент при использовании с zip? - PullRequest
3 голосов
/ 20 мая 2019

Я пытался использовать functools.partial с itertools.count, используя zip с помощью itertools.count ():

g = functools.partial(zip, itertools.count())

При вызове g с такими входами, как "abc", "ABC", я заметил, что itertools.count () таинственно "прыгает".

Я думал, что должен получить тот же результат, что и непосредственное использование zip с itertools.count ()? как:

>>> x=itertools.count();
>>> list(zip("abc",x))
[('a', 0), ('b', 1), ('c', 2)]
>>> list(zip("ABC",x))
[('A', 3), ('B', 4), ('C', 5)]

Но вместо этого я получаю следующее - обратите внимание, что начальный индекс при втором вызове g равен 4 вместо 3:

>>> g = functools.partial(zip, itertools.count())
>>> list(g("abc"))
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> list(g("ABC"))
[(4, 'A'), (5, 'B'), (6, 'C')]

Ответы [ 2 ]

6 голосов
/ 20 мая 2019

Обратите внимание, что вы получите тот же результат, если ваш оригинальный код использует аргументы в том же порядке, что и ваш измененный код:

>>> x = itertools.count()
>>> list(zip(x, "abc"))
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> list(zip(x, "ABC"))
[(4, 'A'), (5, 'B'), (6, 'C')]

zip() сначала пробует свой первый аргумент, затем второй, затем третий ... и останавливается, когда один из них исчерпан.

В написанном выше правописании после того, как "abc" исчерпано, оно возвращается к первому аргументу и получает 3 из x. Но его второй аргумент уже исчерпан, поэтому zip() останавливается, и 3 молча теряется.

Затем он переходит ко второму zip() и начинается с получения 4 от x.

partial() действительно не имеет к этому никакого отношения.

4 голосов
/ 20 мая 2019

Будет легко понять, почему, если вы инкапсулируете itertools.count() внутри функции:

def count():
    c = itertools.count()
    while True:
        v = next(c)
        print('yielding', v)
        yield v

g = functools.partial(zip, count())
list(g("abc"))

Вывод будет

yielding 0
yielding 1
yielding 2
yielding 3
[(0, 'a'), (1, 'b'), (2, 'c')]

Вы увидите, что zip будетоцените следующий аргумент из count() (таким образом, будет получено дополнительное значение 3), прежде чем он поймет, что во второй итерации больше ничего не осталось.

В качестве упражнения переверните аргументы, и вы увидите, что оценка немного отличается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...