web-dev-qa-db-ja.com

Python whileループの条件中に変数に値を割り当てる

Python構文に関する簡単な質問です。whileループの条件の間に関数から変数に値を割り当てたいと思います。関数から返された値がfalseの場合、ループは壊れます。 。私はPHPでそれを行う方法を知っています。

while (($data = fgetcsv($fh, 1000, ",")) !== FALSE) 

ただし、Pythonで同様の構文を試すと、構文エラーが発生します。

20
Borut Flis

式では代入を使用できません。割り当て自体はステートメントであり、Pythonステートメントを組み合わせることはできません。

これは、言語設計者が行った明示的な選択です。 2つの=を使用して等しいかどうかをテストするつもりで、誤って1つの==を使用して割り当てるのは非常に簡単です。

割り当てをループ内に移動するか、割り当てをループの前にして、ループ自体に新しい値を割り当てます。

具体的な例として、Python csv module はより高レベルのAPIを提供し、csv.reader()代わりに:

with open(csvfilename, 'rb') as csvfh:
    reader = csv.reader(csvfh)
    for row in reader:

Iまれに、ループ構造で割り当てる必要がある場合。通常、当面の問題を解決する(はるかに)優れた方法があります。

つまり、Python 3.8以降、言語は:=を代入演算子として使用して、実際に代入式を持ちます。- PEP 572 を参照してください。代入式は実際にはたとえば、作成するリストにメソッドの戻り値を含める必要があり、その値をテストで使用できるようにする必要がある場合など、リストの内包表記に役立ちます。

ここで、ジェネレータ式を使用する必要があります。

absolute = (os.path.abspath(p) for p in files)
filtered = [abs for abs in absolute if included(abs)]

しかし、割り当て式を使用すると、os.path.abspath()呼び出しをインライン化できます。

filtered = [abs for p in files if included(abs := os.path.abspath(p))]
28
Martijn Pieters

Pythonではできません。式に代入する必要はありません。少なくとも、=の代わりに==を誤って入力したり、その逆を行ったりすることがないようにしてください。

従来のPythonスタイルは、Trueとbreakの間だけ使用するものです。

while True:
    data = fgetcsv(fh, 1000, ",")
    if not data:
        break
    # Use data here

しかし、最近はジェネレーターに入れます。

def data_parts(fh):
    while True:
        data = fgetcsv(fh, 1000, ",")
        if not data:
            break
        yield data

そのファイルを使用するコードでは、醜さは隠されています。

for data in data_parts(fh):
    # Use data here

もちろん、実際にCSVを読んでいる場合は、csvモジュールを使用します。

17
RemcoGerlich

私は少し書きましたPythonモジュール、これは let と呼びます。これにより、関数が許可されている任意の場所で変数の割り当てを実行できます。

次のようにインストールします。

pip install let

私は以下があなたが探しているものを達成すると信じています:

from let import let

while let(data = fgetcsv(fh, 1000, ',')):
    # Do whatever you'd like with data here

しかし、Duncanのコメントiterを使用するという元の質問は興味深いです。私は彼がそれを育てるまでその機能を知りませんでした、そして私は今それが私のものより良い解決策であるかもしれないと信じています。それは議論の余地があります-iterは明示的に提供されるセンチネルを必要としますが、私のものは気にせず、fgetcsvFalsey値を返すのを単に待ちます。

4
ArtOfWarfare