Я вижу, как и предсказывалось, что типичный и самый популярный ответ использует очень специализированные генераторы для «чтения 4 байтов за раз». Иногда общность не сложнее (и гораздо полезнее ;-), поэтому я предложил вместо этого следующее очень общее решение:
import operator
def funlooper(afun, *a, **k):
wearedone = k.pop('wearedone', operator.not_)
while True:
data = afun(*a, **k)
if wearedone(data): break
yield data
Теперь желаемый заголовок цикла: for len_name in funlooper(data.read, 4):
.
Редактировать : сделано гораздо более общим с помощью идиомы wearedone
, поскольку комментарий обвинил мою чуть менее общую предыдущую версию (жестко закодировать выходной тест как if not data:
) в "скрытой зависимости", все! -)
Обычный швейцарский армейский нож зацикливания, itertools
, тоже подойдет, конечно, как обычно:
import itertools as it
for len_name in it.takewhile(bool, it.imap(data.read, it.repeat(4))): ...
или, что вполне эквивалентно:
import itertools as it
def loop(pred, fun, *args):
return it.takewhile(pred, it.starmap(fun, it.repeat(args)))
for len_name in loop(bool, data.read, 4): ...