Функция sentinel()
возвращает итераторы, выдающие fillvalue
ровно один раз.Общее число fillvalue
с, полученное всеми итераторами, возвращаемыми sentinel()
, ограничено n-1
, где n
- количество итераторов, переданных izip_longest()
.После того, как это число fillvalue
s будет исчерпано, дальнейшая итерация по итератору, возвращенному sentinel()
, вызовет IndexError
.
Эта функция используется для определения того, были ли исчерпаны все итераторы: Каждый итераторchain()
ed с итератором, возвращаемым sentinel()
.Если все итераторы исчерпаны, итератор, возвращаемый sentinel()
, будет повторяться в течение n
-го раза, что приводит к IndexError
, вызывая конец izip_longest()
по очереди.
Пока чтоЯ объяснил, что делает sentinel()
, а не как это работает.Когда вызывается izip_longest()
, оценивается определение sentinel()
.При оценке определения также оценивается аргумент по умолчанию sentinel()
, один раз за вызов izip_longest()
.Код эквивалентен
fillvalue_list = [fillvalue] * (len(args)-1)
def sentinel():
yield fillvalue_list.pop()
Сохранение этого в аргументе по умолчанию, а не в переменной во вложенной области видимости - это просто оптимизация, равно как и включение .pop
в аргумент по умолчанию, поскольку оно сохраняетпросматривая его каждый раз, когда итератор, возвращаемый sentinel()
, повторяется.