Как запрограммировать разнородную обработку итерируемых объектов?
Есть контейнер, содержащий итератор. Соответственно, к контейнеру можно применить конструкцию for p in container.
Но в данном случае она не очень подходит, поскольку возвращаемые объекты нужно обрабатывать по-разному. Несколько первых, возможно, придётся вообще пропустить, а из последующих выделять определённую часть, склеивая её из нескольких последовательных объектов, и эти склеенные куски поштучно возвращать обратно в вызывающую функцию (очевидно, генератором).
Собственно вопрос: как это красиво запрограммировать?
Я не придумал ничего лучше, чем в генераторе написать два цикла, читающих пакеты вручную с помощью next(). Первый цикл игнорирует все пакеты, пока не встретит пакет с определённым флажком, второй накапливает содержимое очередных пакетов, пока не встретит очередной такой флажок. Как встретит - возвращает накопленное с предыдущего флажка.
Но как-то оно некрасиво выглядит. Есть какие-нибудь более изящные способы записать эту логику?
Или всё же лучше использовать один цикл for по всем объектам, а текущее состояние запоминать в дополнительных переменных?
Чтоб было понятно, откуда такая задача: это обработка транспортного потока (MPEG TS, transport stream). Возвращаемые итератором объекты - это отдельные транспортные пакеты. Payload их представляет собой MPEG PES (program elementary stream), порезанный на кусочки по 184 байта, соответственно, PES-пакеты надо собирать из этих кусочков и возвращать целиком. Транспортный пакет, в котором начинается PES-пакет, идентифицируется по флагу payload_unit_start_indicator. Если первый пакет в потоке такого флага не имеет, то до ближайшего пакета с этим флагом все транспортные пакеты надо пропустить, в них содержится только часть PES-пакета, без начала она не имеет смысла.
Но в данном случае она не очень подходит, поскольку возвращаемые объекты нужно обрабатывать по-разному. Несколько первых, возможно, придётся вообще пропустить, а из последующих выделять определённую часть, склеивая её из нескольких последовательных объектов, и эти склеенные куски поштучно возвращать обратно в вызывающую функцию (очевидно, генератором).
Собственно вопрос: как это красиво запрограммировать?
Я не придумал ничего лучше, чем в генераторе написать два цикла, читающих пакеты вручную с помощью next(). Первый цикл игнорирует все пакеты, пока не встретит пакет с определённым флажком, второй накапливает содержимое очередных пакетов, пока не встретит очередной такой флажок. Как встретит - возвращает накопленное с предыдущего флажка.
Но как-то оно некрасиво выглядит. Есть какие-нибудь более изящные способы записать эту логику?
Или всё же лучше использовать один цикл for по всем объектам, а текущее состояние запоминать в дополнительных переменных?
Чтоб было понятно, откуда такая задача: это обработка транспортного потока (MPEG TS, transport stream). Возвращаемые итератором объекты - это отдельные транспортные пакеты. Payload их представляет собой MPEG PES (program elementary stream), порезанный на кусочки по 184 байта, соответственно, PES-пакеты надо собирать из этих кусочков и возвращать целиком. Транспортный пакет, в котором начинается PES-пакет, идентифицируется по флагу payload_unit_start_indicator. Если первый пакет в потоке такого флага не имеет, то до ближайшего пакета с этим флагом все транспортные пакеты надо пропустить, в них содержится только часть PES-пакета, без начала она не имеет смысла.
iterator = container.__iter__()
while True:
packet = iterator.next()
if packet.payload_unit_start_indicator:
break
pes = []
while True:
pes.append(packet.payload)
packet = iterator.next()
if packet.payload_unit_start_indicator:
yield ''.join(pes)
pes = []