質問
したいループまでのヒットのファイルのようなオブジェクトのがんの発見"を明文について教えてください"は、私の疑い眺めないはずである。:-)
私はストリーム(この場合、このStringIOオブジェクトが、私は約一般の場合もある店舗は、未知数の記録"<length><data>"形式の例:
data = StringIO("\x07\x00\x00\x00foobar\x00\x04\x00\x00\x00baz\x00")
現在、などの設備を導入し、試作から本当に嬉しかったで読むことは何だと思いど)に初期化されたループのう少し国連Pythonic:
len_name = data.read(4)
while len_name != "":
len_name = struct.unpack("<I", len_name)[0]
names.append(data.read(len_name))
len_name = data.read(4)
C-言語だわる read(4)
の while
's"試験条項があることに対して機能しています。他の考え方を達成。
解決
あなたはセンチネルとを ITER()繰り返し処理を組み合わせることができます:
for block in iter(lambda: file_obj.read(4), ""):
use(block)
他のヒント
見たことがありま方に対して繰り返し処理を実行するラインテキストファイルとは何ですか?
for line in file_obj:
use(line)
きんで自分の発電機:
def read_blocks(file_obj, size):
while True:
data = file_obj.read(size)
if not data:
break
yield data
for block in read_blocks(file_obj, 4):
use(block)
参照:
私はすでに述べた反復子ベースのソリューションは、forループの中にこれを有効にすることを好みます。直接書き込ま別の解決策は、Knuthの「ループ半」です。
while 1:
len_name = data.read(4)
if not len_name:
break
names.append(data.read(len_name))
あなたはそれが簡単に独自のジェネレータに掲揚し、forループとして使われていますどのように比較することによって見ることができます。
私は典型的な、最も人気のある答えは「一度に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): ...
PythonでEOFマーカーは、あなたが持っているものので、空の文字列はイテレータでこれをラップする関数を記述することなく、あなたが得ようとしている最高にかなり近いです。私は同じようwhile
を変更することで、もう少し神託のように書くことができます:
while len_name:
len_name = struct.unpack("<I", len_name)[0]
names.append(data.read(len_name))
len_name = data.read(4)
私は読みやすさのための機能とイテレータ再Tendayiの提案で行くと思います:
def read4():
len_name = data.read(4)
if len_name:
len_name = struct.unpack("<I", len_name)[0]
return data.read(len_name)
else:
raise StopIteration
for d in iter(read4, ''):
names.append(d)