5

たとえば、次のコードで:

def product(list):
    p =1
    for i in list:
        p *= i
    return p

このコードを見つけましたが、そのすべての部分を説明できるようにする必要があります。

4

5 に答える 5

4

通常p *= iは と同じp = p * iです。

場合によっては異なる場合があり、すでに投稿されている説明では十分に明確ではないと思うので、次のようにします。

p が変更可能なオブジェクトの場合は異なる場合があります。その場合、インプレース*=は新しいオブジェクトを作成する代わりに元のオブジェクトを変更することがあります。qこれらのそれぞれで何が起こるかを比較してください。

>>> p = q = [2]
>>> p *= 5
>>> p
[2, 2, 2, 2, 2]
>>> q
[2, 2, 2, 2, 2]

>>> p = q = [2]
>>> p = p * 5
>>> p
[2, 2, 2, 2, 2]
>>> q
[2]

pインプレース バージョンはサブ式を 1 回しか評価しないため、副作用のある複雑な式である場合も異なります。たとえば、次のようになります。

aList[randint(0, 5)] *= 3

次と同じではありません:

aList[randint(0, 5)] = aList[randint(0, 5)] * 3
于 2013-10-21T13:34:29.930 に答える
4

演算子の背後にある考え方a *= bは、 と同じ意味a = a * bです。ほとんどの場合(あなたの場合のように)、まさにこれを行うため、変数に値を掛けて、結果を変数に再度格納します。

を使用した表記の*=方が高速である可能性があり (関連するクラスによって異なります)、いずれにせよ、より明確なバージョンであるため、優先する必要があります。その主な利点は、変数a自体がすでに次のような複雑な式であるかどうかを示していmyGiantValueField[f(42)].getValue()[3]ます。

myGiantValueField[f(42)].getValue()[3] = myGiantValueField[f(42)].getValue()[3] * 3

確かに可読性が低く、コードが2倍になるため、エラーの修正がより起こりやすくなります

myGiantValueField[f(42)].getValue()[3] *= 3

ただし、一般に、演算子は変数*=のメソッドを呼び出して引数を渡すため、 (直感的ではありませんが) とまったく同じ意味になります。__imul__()aba.__imul__(b)

a = a * bと の間に違いがあるのはなぜa *= bですか? 3 つの理由が同時に頭に浮かびますが、それ以上の理由があるかもしれません。

  1. パフォーマンスの観点から、クラスは演算子のみを実装できます (したがって存在していても未定義である可能性があります)。非常に大きな値 (巨大な行列など) と数値の乗算は、結果にメモリを割り当てる必要がないように、インプレースで行う方がよい場合があります (計算後、代入によって元の変数にコピーされる可能性があります)。それは内部的に sth のように andです。*=a * ba *= ba = a * btmp = a * ba = tmp
  2. クラスは、直接乗算を使用するとその使用が直感的ではないことに気付く可能性があるため、*演算子が実装されないままになる可能性があります。例として、コンピューターのスピーカーの音量を表すクラスが考えられます。ボリュームを 2 倍にすることは理にかなっていますが ( volumeKnob *= 2)、使用 (割り当て) せずに計算することはお勧めしません ( x = volumeKnob * 2? ← 何もしないので意味がありません)。
  3. 乗算の結果の型が の型と異なる場合、誤解を招く可能性があるためa、演算子の実装を期待または推奨しません。*=例として、乗算結果が行列 (または数値) になるベクトルである場合がaあります。bその名前__imul__は、反復的に、つまり複数回適用されることを意図していることをすでに示唆しています。しかし、aのタイプが変更された場合、これは問題になります。
于 2013-10-21T12:32:56.293 に答える