変数と代入|Pythonの最初の1行

このページはプロモーション(広告)を含みます。

Pythonの最初の1行(初級・読む20分+演習30分)

この授業のゴール

仕事でどう使うか

税率、割引率、手数料率のような値を、式のあちこちに直接書くと、変更のたびに直し漏れが起きます。値に名前を付けて1か所に書いておけば、直すのは1行で済み、読む人にも「この数字は何か」が伝わります。

路線 この授業の使いどころ
DS(データサイエンティスト) 分析の閾値(しきいち)や対象期間を変数にまとめ、条件を変えた再分析を1行の修正で行う。レポートに「この数字は変数 rate の値」と書ける
ML(機械学習エンジニア) 学習率やデータ分割の割合などのハイパーパラメータ(人が事前に決める設定値)を変数に集め、実験ごとの違いを記録する
DX(DX推進・AI企画) 業務ルールの数値(割引率・手数料率)を、コードの1か所にまとめて仕様書と照合する。ルール変更の影響範囲を小さくする
RS(研究者) サンプルサイズや有意水準などの設定を変数として先頭に置き、論文の記述と一致しているかを確認する

また、代入は「値が時間とともに変わる」ことを表します。いつの時点の値かを追えるかどうかが、のちのバグ探しの力になります。

前提

次の内容を前提にします。

数学の「$=$」は「左右が等しい」という主張でした。この授業では、Pythonの = がそれとは別の意味を持つことを、実行して確かめます。

身近な状況:税率を式のあちこちに書いてしまった

ある店の担当者が、税込価格の計算を次のように書きました。

print(1000 * 1.1)
print(2500 * 1.1)
print(480 * 1.1)

税率が変わったとき、1.1 を3か所とも直さなければなりません。1か所直し忘れると、商品ごとに違う税率で計算した表ができあがります。しかも、1.1 を見ても、それが税率なのか、別の倍率なのかは読み取れません。

値に名前を付けると、次のようになります。

tax_rate = 0.1
print(1000 * (1 + tax_rate))
print(2500 * (1 + tax_rate))
print(480 * (1 + tax_rate))

税率の定義は tax_rate = 0.1 の1行だけです。式を読む人は (1 + tax_rate) を見て「税率を加えた倍率だ」とわかります。この「値に名前を付ける」仕組みが変数で、名前に値を結びつける操作が代入です。

直感的な説明:名前札を値に貼り付ける

変数は「値を入れる箱」と説明されることが多いですが、この教材では名前札を使って考えます。price = 1000 は、1000 という値に price という名前札を貼る操作です。

名前札には、次の性質があります。

  1. 札を貼るときは、値を先に用意してから貼る。右辺の式(1000 * 0.9 など)を先に計算して、できた値に札を貼る。
  2. 同じ名前の札を貼り替えることができる。price = 2000 を実行すると、price の札は 1000 から外れて、2000 に貼り直される。
  3. 貼り替えても、すでに計算してできた別の値には影響しない。discounted = price * 0.9 で 900.0 ができたあとで price を貼り替えても、discounted の札は 900.0 に付いたままである。

数学の等式 $y = 0.9x$ は「$x$ が変われば $y$ も変わる」という関係の宣言でした。Pythonの代入は関係ではなく、その時点の計算結果に名前を付ける操作です。この違いが、この授業の中心です。

正確な定義:代入文と変数名のルール

代入文の書き方は 名前 = 式 です。実行の順序は決まっています。

  1. 右辺の式を先に計算して、値を得る。
  2. その値に、左辺の名前を結びつける。すでに同じ名前があれば、結びつけを置き換える(再代入)。

したがって x = x + 1 は、「現在の x の値に 1 を足した値を、x に結びつけ直す」という意味です。数学の式 $x = x + 1$ は、どんな $x$ でも成り立たない($0 = 1$ になる)矛盾した式ですが、コードでは正しい操作です。

Pythonで「左右が等しいか」を調べるには、==(等号を2つ)を使います。price == 1000 は、等しければ True(真)、違えば False(偽)という真偽の値になります(数値・文字列・真偽値 で扱います)。

記号 意味 例
= 代入:右の値を左の名前に結びつける price = 1000
== 比較:左右が等しいかを調べて True / False を得る price == 1000

変数名のルールは次のとおりです。

名前 使える? 理由
price / unit_price / price2 / _tmp 使える 英字・数字・_ で、先頭が数字でない
2price 使えない 先頭が数字
unit-price 使えない - は引き算と読まれる
unit price 使えない 空白で2つの語に分かれる
class / if / for 使えない Pythonが文法で使う予約語
Price と price 別の名前 大文字と小文字は区別される

名前の付け方の目安は、(1) 何の値か意味がわかる、(2) 単語を _ でつなぐ(unit_price)、(3) 単位や形式を区別する(円なら price_yen、パーセントで持つなら rate_pct、割合なら rate)、の3つです。割合 0.1 とパーセント 10 は別物なので、名前で区別しておくと取り違えを防げます。

段階付き例題:在庫の増減を1行ずつ追跡する

問題:商品の在庫が 100 個ある。30 個売れ、その後 50 個入荷した。各時点の在庫を求める。

ステップ1:状態を表にして予想する。代入のたびに、変数の値がどう変わるかを書きます。

実行した行 右辺の計算 stock の値
stock = 100 100 100
stock = stock - 30 100 − 30 = 70 70
stock = stock + 50 70 + 50 = 120 120

ステップ2:コードにして実行する。

stock = 100
print('初期在庫:', stock)

stock = stock - 30      # 30個売れた
print('販売後:', stock)

stock = stock + 50      # 50個入荷した
print('入荷後:', stock)

print に、コンマ区切りで文字と値を並べると、間に空白を入れて1行に表示されます(printと入力値 で詳しく扱います)。

ステップ3:結果を読む。出力は 初期在庫: 100、販売後: 70、入荷後: 120 です。表の予想と一致しました。

ステップ4:「連動しない」ことを確かめる。在庫の金額(在庫金額 = 単価 × 個数)を計算してから、個数を変えてみます。

unit_cost = 200
stock = 100
stock_value = unit_cost * stock    # この時点の計算結果: 20000
stock = 70                          # 個数だけ書き換える
print(stock_value)
print(unit_cost * stock)

出力は 20000 と 14000 です。stock_value は 100 個だった時点の計算結果のままです。stock を変えたあと、最新の在庫金額が必要なら、もう一度計算する必要があります。Excelのセルは参照先が変わると自動で再計算されますが、Pythonの変数はそうなりません。

操作して理解する:入れ替えと予想

2つの変数 a と b の値を入れ替える問題で、代入の順序を確かめます。まず誤った書き方を実行して、結果を予想してください。

a = 3
b = 5
a = b      # a は 5 になる。元の 3 はどこにも残っていない
b = a      # b には、いま a が指している 5 が入る
print(a, b)

出力は 5 5 です。a = b を実行した時点で、3 に貼ってあった a の札が 5 に貼り替わり、3 を指す名前がなくなりました。次のように、一時的な名前(tmp)で3を保存しておけば、入れ替えができます。

a = 3
b = 5
tmp = a    # 3 を一時的に保存する
a = b      # a は 5
b = tmp    # b は保存しておいた 3
print(a, b)

出力は 5 3 です。Pythonには a, b = b, a という書き方もあります。右辺の b, a を先にまとめて計算し、その結果を左辺の a, b に同時に結びつけるので、一時的な名前が要りません。

a = 3
b = 5
a, b = b, a
print(a, b)

次に、自分で値を変えてみてください。a = 3, b = 5 を a = 10, b = 20 に変えると、出力は 20 10 になるはずです。代入の前後で、どの名前がどの値を指しているかを、紙に図で描きながら追うと、理解が確かになります。

発展:代入は「値のコピー」とは限らない

数値や文字列のようにあとから中身を書き換えられない値(不変:immutable)では、b = a のあと a を貼り替えても b には影響しません。一方、リスト(値を複数並べて持つ型。「リストとタプル」(有料版) で扱います)は、中身を後から書き換えられる可変(mutable)な値で、挙動が異なります。

a = [1, 2]
b = a          # b は、a と同じリストに名札を貼る。コピーではない
b.append(3)    # 同じリストに 3 を追加する
print(a)       # a と b は同じリストを指しているので [1, 2, 3]

c = a.copy()   # 中身を複製した新しいリスト
c.append(4)
print(a, c)

出力は [1, 2, 3] と [1, 2, 3] [1, 2, 3, 4] です。b = a は「同じものに別の名前を付ける」だけなので、b の変更が a にも見えます。コピーが必要なときは .copy() で複製します。コピーと参照の詳しい違いは 「浅いコピーと参照」(有料版) で扱います。この現象は、pandas のデータを扱うときに「元の表を変えるつもりがなかったのに書き換わっていた」という失敗として現れます。

なお、名前の通用範囲(スコープ)、関数の中の変数、global といった話題は 「ローカル変数とスコープ」(有料版) で扱います。この授業の範囲では、「名前は値に貼る札であり、貼り替えは以前の計算結果に影響しない」ことを押さえれば十分です。

よくある失敗

失敗1:Excelのように、元の値を変えれば結果も変わると考える

誤り:discounted を計算したあとで定価を変え、discounted も更新されると期待する。

price = 1000
discounted = price * 0.9
price = 2000
print(discounted)

出力は 900.0 です。discounted は price が 1000 だった時点の計算結果で、price を変えても再計算されません。期待した 1800.0 を得るには、price = 2000 の後で、もう一度 discounted = price * 0.9 を実行します。

直し方:「値を変えたら、その値を使う計算をやり直す」順序でコードを書く。一度に再計算したいなら、計算をまとめて関数にします(「関数と引数」(有料版))。

失敗2:`=` と `==` を取り違える

誤り:「等しいか調べたい」つもりで = を書く。下のコードは、誤りを文字列に入れて文法チェックだけを行います。

price = 1000
print(price == 1000)     # 比較:True
print(price == 900)      # 比較:False

code = '1000 = price\n'  # 誤り:数値 1000 に名前を結びつけることはできない
try:
    compile(code, 'sample.py', 'exec')
except SyntaxError as e:
    print(type(e).__name__, '行', e.lineno)

出力は True、False、SyntaxError 行 1 です。price == 1000 は比較で、結果が True / False になります。1000 = price は「1000という値に名前を付ける」という意味になってしまい、文法として許されません。

さらに怖いのは、文法として通る = の誤用です。price = 900 と書いて「900円か確認した」つもりになると、price が書き換わるだけで、確認は行われません。直し方:確認したいときは ==、値を設定したいときは = と、目的で使い分ける。

失敗3:名前のタイプミスと大文字小文字の違い

誤り:Price(先頭が大文字)と price を同じ名前だと思い込む。

code = 'price = 1000\nprint(Price * 0.9)\n'
try:
    exec(compile(code, 'sample.py', 'exec'), {})
except Exception as e:
    print(type(e).__name__, ':', e)

出力は NameError : name 'Price' is not defined です。Pythonは Price と price を別の名前として扱います。rate を rat と打ち間違えた場合も同じ NameError になります。

直し方:エラーメッセージの名前と、代入した名前を1文字ずつ見比べる。エディタの補完機能を使うと、打ち間違いを減らせます。エラーが出れば気づけますが、似た名前を2つ作ってしまった場合(rate と rate2)は、エラーが出ずに古い値を使い続けるので、名前の付け方を整理しておきます。

失敗4:組み込み関数と同じ名前を変数に使い、関数が使えなくなる

誤り:合計を表す変数に sum という名前を付ける。sum はPythonがあらかじめ持っている「合計を求める関数」の名前でもあります。

sum = 10
code = 'print(sum([1, 2, 3]))\n'
try:
    exec(compile(code, 'sample.py', 'exec'), {'sum': sum})
except Exception as e:
    print(type(e).__name__, ':', e)
del sum
print(sum([1, 2, 3]))

最初の出力は TypeError : 'int' object is not callable です。sum という名前札が整数 10 に貼り替わったため、sum(...) が「整数を関数として呼び出す」ことになり、エラーになります。del sum で自分の貼り付けを外すと、元の関数が使え、最後の行は 6 を表示します。

直し方:total、total_price のように具体的な名前にする。sum のほか、max、min、list、print なども上書きしないようにします。

まとめ

用語

変数(variable)

値に付けた名前。コードの中でその名前を書くと、結びつけられた値が使われる。

代入(assignment)

名前 = 式 の形で、式の値を計算して名前に結びつける操作。

再代入(reassignment)

すでにある名前に、別の値を結びつけ直すこと。以前の値は(他に名前がなければ)使えなくなる。

予約語(reserved word / keyword)

if、for、class のように、Pythonの文法で使われる語。変数名には使えない。

よくある質問

変数は「箱」と習いましたが、名札と何が違いますか?

ほとんどの場面で同じように考えられます。違いが出るのは、b = a のあとに a と b が同じ中身を指す場合です。リストのように中身を書き換えられる値では、片方の変更がもう片方にも見えます。この教材は、その現象を説明しやすい「名前札」で説明します。

なぜ `x = x + 1` のような式が書けるのですか? 数学では成り立たないのでは?

Pythonの = は等式の主張ではなく、右辺を計算して左辺の名前に結びつける操作だからです。数学の等式は「左右が等しい」という関係を言いますが、代入は「今の値から新しい値を作って置き換える」手順です。

変数名は日本語でも付けられますか?

Pythonは日本語の変数名も許しますが、共同作業では英語(またはローマ字)で意味のある名前を付けるのが一般的です。ツールや他の言語との連携で問題が起きにくいためです。会社やチームの命名規則があれば、それに従います。

短い名前(`a`、`x`)と長い名前のどちらがよいですか?

数式をそのまま写す小さな計算では x や a も使われますが、仕事のコードでは unit_price や tax_rate のように意味を持つ名前が読みやすいです。「3か月後の自分や他人が、名前だけで何の値かわかるか」を基準にします。

変数に入れた値が途中で変わっていないか、どう確認しますか?

疑わしい行の前後に print(変数名) を入れ、値を確かめます。この授業で行ったように、各行の後の値を表にして予想し、実際の出力と比べるのが基本です。値と一緒に型も見たいときは 数値・文字列・真偽値 の type() を使います。

変数を使うと、計算を間違える危険は増えませんか?

名前の付け間違いや再代入の順序の誤りという新しい危険は増えます。一方、数字を式のあちこちに書く場合の直し漏れは減ります。対策は、意味のある名前、計算の途中結果の確認、期待値との照合です。

確認問題

問1 次のコードを実行したときの出力はどれか。

x = 5
x = x + 1
print(x)
  1. ① エラーになる(x = x + 1 は成り立たない式だから)
  2. ② 51
  3. ③ 6
  4. ④ 5
解答と解説

正解:③

右辺の x + 1 を先に計算して 6 を得て、その値に x を結びつけ直します。代入は等式の主張ではなく操作です。

問2 次のコードの出力はどれか。

price = 1000
discounted = price * 0.9
price = 2000
print(discounted)
  1. ① 900.0
  2. ② 1800.0
  3. ③ 2000
  4. ④ エラーになる
解答と解説

正解:①

discounted は price が 1000 だった時点の計算結果です。後から price を変えても、再計算は自動では行われません。

問3 次の変数名のうち、Pythonで使えるものはどれか。

  1. ① class
  2. ② unit_price
  3. ③ 2nd_price
  4. ④ unit-price
解答と解説

正解:②

変数名は、英字・数字・_ からなり、先頭は数字以外で、予約語でない必要があります。

問4 price が 1000 のとき、print(price == 1000) は何を表示するか。

  1. ① 1000
  2. ② エラー(== は存在しない記号)
  3. ③ price
  4. ④ True
解答と解説

正解:④

== は左右が等しいかを比べる演算で、結果は真偽値 True / False です。この場合は等しいので True です。

問5 code に price = 1000 と print(Price) を入れて実行したら NameError になった。原因として最も可能性が高いものはどれか。

  1. ① Price と price は大文字小文字が違うので別の名前として扱われた
  2. ② Pythonが print を理解できなかった
  3. ③ price = 1000 の = が比較になっている
  4. ④ 1000 が大きすぎて計算できない
解答と解説

正解:①

Pythonは大文字と小文字を区別します。Price は一度も代入していない名前なので、NameError になります。

問6 a = 1、b = 2 の状態から a = b、b = a の2行を順に実行した。a と b の値はどうなるか。

  1. ① a は 1、b は 1 になる
  2. ② a も b も 2 になる
  3. ③ a は 2、b は 1 になる(入れ替わる)
  4. ④ a は 1、b は 2 のまま
解答と解説

正解:②

a = b で a が 2 に貼り替わった時点で、元の 1 を指す名前はなくなります。続く b = a は 2 を b に入れるだけです。入れ替えには一時的な名前か a, b = b, a が必要です。

次に学ぶこと

次は 数値・文字列・真偽値 で、値の種類(型)を学びます。数値と文字列と真偽値は別の種類で、"1000" と 1000 は計算の結果が変わります。

この授業の確認問題だけでモジュールの習得とはしません。PY01 の総合テストと、別の条件の自力課題で判定します。リストなど複数の値をまとめる変数は 「リストとタプル」(有料版) で扱います。

キャリア学習:データサイエンティスト・機械学習エンジニア・DX推進・研究者を目指す人の学習アプリ。164モジュール・984授業を、ブラウザで動くSQLとPythonの演習で。基礎と各分野の最初のモジュールは無料。全部は2,980円の買い切り。

アプリを無料で開く有料版と無料版の違い