Например, когда я в цикле добавляю серии к графику и мне надо циклически перебирать цвета из заранее заданного списка, при этом число серий больше числа цветов и некоторые итерации цикла могут пропускать создание серии (что не должно приводить к пропуску цвета)
Вообще в питоне объект итератора, создаваемый iter - тоже встречается довольно редко, что приводит к тому что чтоб где-то использовать next - надо ещё и явно создать объект итератора на основе sequence
В очень редких случаях использую для взятия первого элемента из коллекции s неизвестной и возоможно нулевой длины
first_or_none = next(iter(s), None)
Читабельность этого под большим вопросом, часто вместо этого делаю
seq_start = list(s)[:1]
который вернёт коллекцию нулевой или единичной длинны, что может быть более наглядно чем значение по умолчанию
Так что на мой взгляд - next годится только для написания продвинутых утилитных функций в стиле more-itertools, вне такого библиотечного кода применений почти не вижу.
Что имелось ввиду под избежать break/continue - вообще не понял. Имеется ввиду работа с явно созданным объектом итератора в цикле while вместо for __ in коллекция?
А если чуть серьёзнее, то когда мы учились, были, например, шутки про то, как поделить на разыменованный указатель (/*p...) и т.п.
А тут целая тема: «Нравится ли вам оператор for»
Чаще всего с generator expressions, например тут поиск по dict/list:
@staticmethod
def identify(serial: str) -> Product | None:
return next((p for (s, p) in SERIAL_MAP.items() if serial.startswith(s)), None)
next((i[1] for i in parts if i[0] == "model"), None)
И чё это сразу «если вообще пользуетесь»?
Никогда что ли однострочники по приколу не писали? Я имею в виду забористые, типа
В чом цель опроса? Реализация итераторов в питоне ублюдочна, так и так, но именно на ней построены все штатные циклы. По итогу все эти констракции являются обёртками над (*Py_TYPE(it)->tp_iternext)(it).
На самом деле сама реализация байткода FOR_ITER говорит о том, насколько это убогая штука: https://github.com/python/cpython/blob/main/Python/ceval.c#L3705-L3716
Они сделали специальную обработку для индексирования по массивам с целочисленным индексом, потому что цирк с конями и клоунами для простой итерации реально не нужен.
Забавно то, что внутри CPython есть разница между «итератор вернул None» ( Py_NewRef(Py_None) ) и «итерирование закончилось» ( PyErr_SetNone(PyExc_StopIteration) ) — но в языке это разделение недоступно. И оно немудрено, потому что язык создавался во времена, когда обрабатывать ошибки было немодно. А вы думаете почему люди ноют про стектрейсы на два экрана?
Что захватится? Внешняя s, COPY_FREE_VARS и все дела.
ОК. А тут что захватится?
s = 1
def f():
l = lambda: s
# ...
s = 2
return l
Локальная s. Тихий и спокойный MAKE_CELL, Вроде норм, без nonlocal же.
Однако s была перекрыта черте где ниже по контексту. Где мои эксепшны о факте перекрытия имени после его использования, Питон?
Не, конечно лучше всегда для итерации делать my_list[1:], т.к. однородность кода важна. А обычно когда в списке надо первый элемент пропускать, то окажется что и второй надо иногда или последний. А так однороднее будет. Другой вопрос в производительности - там у next есть плюсы. С другой стороны слайс это множество элементов а next-ом их по штуке обрабатывать (что может оказаться и медленнее, смотря как обрабатывать). Если ты попутал извлечение первого элемента, как my_list[:1] то такое имеет право на жизнь, но не более того.
Хах, поведение глобальных переменных меняли в разных версиях питона. То есть, твой код захватит глобальную s на двойке и локальную на тройке. Прикол с «опять вася испортил глобальную переменную, причём, его-то код работает и тесты проходят, потому что он для себя значение правильное установил» настолько всех достало, что они наконец решили это исправить.
Я давно грю, что питон — это фрактал бездарной архитектуры или её отсутствия, «один посрал — второй поел».
Очень редко реально нужен, т.к. в целом iterables идиоматичнее обходить без него. Но, вот, например, конкретный кейс, когда удобно было использовать.
with open(filename, 'r') as f:
rdr = csv.reader(f)
hdr = next(rdr) # тут мне нужен был только заголовок
p = Parser(hdr) # <- для вот этого друга
with open(filename+'.result.csv', 'w') as f2:
wrt = csv.writer(f2)
wrt.writerow(hdr)
for i, row in enumerate(rdr):
pass
Редко, очень. Долго пытался вспомнить, потом увидел кусок кода в одном из комментов. Обычно только если логика настолько упорота что приходится вручную резать данные