
Pythonの代入 = について詳しく解説し、算術演算子と代入を組み合わせた代入演算子について学ぶ。また、他のプログラミング言語のようなインクリメント演算子、デクリメント演算子がないことについて触れる。
サンプル・プログラム
代入
これまで見てきたように、Python におけるイコール = は等号を表すのではなく、代入という作用を持つ。 \( op1 = op2 \) のようにして用い、オペランド \( op2 \) を \( op1 \) に代入する。たとえば \( x=1+2 \)なら、\( 1+2 \) の計算結果を変数 \( x \) に代入する。

少しハードウェア寄りの話をすると、代入 = は、右のオペランドが格納されているアドレス(メモリ上の場所を示す住所のような値)を変数に代入する。

少しハードウェア寄りの話をすると、代入 = は、右のオペランドが格納されているアドレス(メモリ上の場所を示す住所のような値)を変数に代入する。
# リスト
a = [1, 2, 3] # リストa
b = a # リストb
print("a = " + str(a))
print("b = " + str(b))
# 比較演算
print("a is b : " + str(a is b))
# ミュータブル
a[0] = 99
print("a = " + str(a))
print("b = " + str(b))
# 比較演算
print("a is b : " + str(a is b))

ミュータブル
たとえばプログラム "mutable.py" では、リスト [1, 2, 3] が格納されているアドレスをかりに300番地とすると、変数 a には300番地を代入する。次に、変数 a の値を変数 b に代入するので、変数 b にも300番地が入る。つまり、変数 a と b は同じリストの実体 [1, 2, 3] を指していることになる。

このため、変数 a の冒頭の値に99を再代入してやると、それに連動して変数 b の冒頭の値も変わる。これをミュータブル(変更可能)という。

「3.3 比較演算子とブール演算子」で紹介したように、is演算子を使ってみると、再代入の前後で同一性が失われていないことが分かる。

このため、変数 a の冒頭の値に99を再代入してやると、それに連動して変数 b の冒頭の値も変わる。これをミュータブル(変更可能)という。

「3.3 比較演算子とブール演算子」で紹介したように、is演算子を使ってみると、再代入の前後で同一性が失われていないことが分かる。
# int
a = 1 # int a
b = a # int b
print("a = " + str(a))
print("b = " + str(b))
# 比較演算
print("a is b : " + str(a is b))
# イミュータブル
a = 99
print("a = " + str(a))
print("b = " + str(b))
# 比較演算
print("a is b : " + str(a is b))

イミュータブル
プログラム "immutable.py" も同様に、整数 1 が格納されているアドレスをかりに400番地とすると、変数 a には400番地を代入する。次に、変数 a の値を変数 b に代入するので、変数 b にも400番地が入る。この時点では、変数 a と b は同じ整数の実体 1 を指していることになる。

ところが、変数 a に99に再代入しても、変数 b は変化しない。これをイミュータブル(変更不可)という。

is演算子を使ってみると、最初は同一性であったが、再代入後に同一性が失われていることが分かる。

ところが、変数 a に99に再代入しても、変数 b は変化しない。これをイミュータブル(変更不可)という。

is演算子を使ってみると、最初は同一性であったが、再代入後に同一性が失われていることが分かる。
複合代入演算子
Python は、他のプログラミング言語と同様、代入と算術演算子と組み合わせた複合代入演算子(単に代入演算子と呼ぶことも)が用意されている。たとえば a += 2 は、変数 \( a \) に2を加算し、変数 \( a \) に代入するという働きをする。
演算子 | 意味 |
---|---|
+= | 左辺と右辺を加算した結果を左辺に代入する |
-= | 左辺から右辺を減算した結果を左辺に代入する |
*= | 左辺と右辺を乗算した結果を左辺に代入する |
/= | 左辺を右辺で除算した結果を左辺に代入する |
//= | 左辺を右辺で除算した結果(整数部)を左辺に代入する |
%= | 左辺を右辺で除算した剰余をを左辺に代入する |
**= | 左辺を右辺をべき乗した結果を左辺に代入する |
&= | 左辺と右辺をビット論理積した結果を左辺に代入する |
|= | 左辺と右辺をビット論理和した結果を左辺に代入する |
^= | 左辺と右辺をビット排他的論理和した結果を左辺に代入する |
>>= | 左辺を右辺の値だけ右シフトした結果を左辺に代入する |
<<= | 左辺を右辺の値だけ左シフトした結果を左辺に代入する |
新しい代入演算子
これまで、算術演算子、ビット演算子、シフト演算子、代入演算子を学んできたが、これらは、かならず「計算結果」を返す。
一方、Python の代入 = を、わざと代入演算子と呼ばなかったのは、他のプログラミング言語と違って計算結果を返さないからだ。代入 = は演算子ではなく、文法構造の1つなのである。
たとえば JavaScript、PHP、C++などで
Python では = が値を返さないため、式のエラーになっているのだ。

そこで、Python 3.8では、他言語の代入演算子と同じ働きをする 代入式 := が導入された。
一方、Python の代入 = を、わざと代入演算子と呼ばなかったのは、他のプログラミング言語と違って計算結果を返さないからだ。代入 = は演算子ではなく、文法構造の1つなのである。
たとえば JavaScript、PHP、C++などで
b = (a = 2) * 3を計算すると、\( a = 2, b = 6 \) となる。ところが、Python ではエラーになってしまう。
Python では = が値を返さないため、式のエラーになっているのだ。

そこで、Python 3.8では、他言語の代入演算子と同じ働きをする 代入式 := が導入された。
# 代入式
b = (a := 2) * 3
print("a = " + str(a))
print("b = " + str(b))
インクリメントとデクリメントはない
他のプログラミング言語にある i++ のようなインクリメント演算子や、i-- のようなデクリメント演算子が、Python には用意されていない。だが、これまで学んできた加算代入演算子 i += 1 や減算代入演算子 i -= 1 を使って代用できることが分かるだろう。

インクリメント/デクリメント演算子は、前置式 ++i にするか、後置式 i++ にするかで式の評価の順序が変わるため、シンプルなプログラミングを目指す Pythonでは実装されなかった。

インクリメント/デクリメント演算子は、前置式 ++i にするか、後置式 i++ にするかで式の評価の順序が変わるため、シンプルなプログラミングを目指す Pythonでは実装されなかった。
アンパック代入
代入 = が文法構造であることを端的に示すのがアンパック代入だ。
Python では、たとえばリストの要素を代入 = を使って分解して、別々の変数に代入することができる。これをアンパック代入と呼ぶ。
Python では、たとえばリストの要素を代入 = を使って分解して、別々の変数に代入することができる。これをアンパック代入と呼ぶ。
# アンパック代入(1)
a = [1, 2, 3]
x, y, z = a
print("x = " + str(x))
print("y = " + str(y))
print("z = " + str(z))
アンパック代入で、変数名にアスタリスク * を付けると、その他のデータを格納するという意味になる。
# アンパック代入(2)
a = [1, 2, 3, 4, 5]
x, *y, z = a
print("x = " + str(x))
print("y = " + str(y))
print("z = " + str(z))
アンパック代入を応用すると、簡単に変数の内容を入れ替える(スワップする)ことができる。
a = [1, 2, 3]
b = [7, 8, 9]
print("a = " + str(a))
print("b = " + str(b))
# スワップ
a, b = b, a
print("a = " + str(a))
print("b = " + str(b))
練習問題
次回予告
次回は、Pythonの演算子の優先順位を学ぶ。算術演算子、論理演算子、ビット演算子、シフト演算子、代入演算子について学んできたが、算数で乗除算が加減算に優先するように、これらの演算子が1つの式の中に含まれるときには演算の優先順位がある。演算子が多いので覚えきれないかもしれないが、大丈夫――算数と同じで括弧 (...) を付けることで優先順位をコントロールできるので。
コラム:COBOLとBASICのイコール
Python を含む多くのプログラミング言語では、比較演算子で等しいかどうかを計算するのに == を使うが、COBOL言語ではイコール = である。その代わり、代入は MOVE を使う。

厄介なのは BASIC言語で、比較演算子 = と代入 = が同じである。つまり
では、

COBOL言語や BASIC言語を習ったことがある方は、比較演算をイコール = にしないよう気をつけよう。

厄介なのは BASIC言語で、比較演算子 = と代入 = が同じである。つまり
If a = b Thenこれは変数aとbの値を比較する比較演算であるが、
a = bは変数bをaに代入する代入式となる。
では、
Console.WriteLine(a = b)は、どちらの作用かというと‥‥比較演算である。

COBOL言語や BASIC言語を習ったことがある方は、比較演算をイコール = にしないよう気をつけよう。
(この項おわり)