Pythonの基礎知識(基礎編)

【Pythonの基礎知識】変数と値の動きを通して仕組みを理解しよう

Pythonの学びを進めると、「型」は理解できても、次に壁となるのが「変数と値の関係」です。

同じように代入しているのに、思った結果にならない──その原因は、変数が“値そのもの”ではなく“値を指す仕組み”を持っているからです。

この記事では、変数と値のつながりを丁寧にたどりながら、代入や再代入の裏で何が起きているのかを整理します。

型を学んだあとに訪れる「なぜそうなるのか」という疑問を、具体的なケースを通して見える形にしていきます。

Pythonの基礎知識(基礎編)


🟣 Pythonの基礎知識(基礎編)
📌基本文法から実用テクニックまで、Pythonの土台を固めるステップアップ講座
└─ 【Pythonの基礎知識(基礎編)】仕組みから学ぶ思考と自動化のプログラミング講座
  ├─ STEP 0:Pythonを動かす“仕組み”を理解する
  | ├─【Pythonの基礎知識】Pythonを動かす環境とは何か? “自分専用の環境”を作る
  | ├─【Pythonの基礎知識】Hello Worldの裏側にある実行の仕組み
  | └─【Pythonの基礎知識】Pythonのファイル構造と実行パスを理解する
  |
  ├─STEP 1:Pythonで“考える仕組み”を作る(思考編)
  | ├─【Pythonの基礎知識】データ型で世界を定義する|数・文字・真偽の正体
  | ├─【Pythonの基礎知識】変数と値の動きを通して仕組みを理解しよう
  | ├─【Pythonの基礎知識】条件分岐で“判断を任せる”仕組みを作る
  | ├─【Pythonの基礎知識】for文で“人の手”を離す仕組みを作る
  | └─【Pythonの基礎知識】while文で“継続する仕組み”を作る
  |
  ├─STEP 2:Pythonで“情報を扱う仕組み”を作る(構造編)
  | ├─【Pythonの基礎知識】コレクション型の正しい選び方(list, tuple, dict, set)
  | ├─【Pythonの基礎知識】リストで情報を整理し、仕組みに流れを持たせる
  | ├─【Pythonの基礎知識】辞書型でデータを“意味”で管理する
  | └─【Pythonの基礎知識】集合型で重複を排除し、無駄をなくす仕組みを作る
  |
  ├─STEP 3:Pythonで“動きを再利用する仕組み”を作る(関数・モジュール編)
  | ├─【Pythonの基礎知識】関数で処理を再利用する|“人間の手順”を仕組みに変える
  | ├─【Pythonの基礎知識】引数と戻り値で“情報のやりとり”を自動化する
  | ├─【Pythonの基礎知識】モジュールとパッケージで“仕組みを部品化”する
  | └─【Pythonの基礎知識】importの裏側を理解し、コードを分離する設計思考
  |
  ├─STEP 4:Pythonで“データを扱う仕組み”を作る(入出力・永続化編)
  | ├─【Pythonの基礎知識】ファイル操作でデータを読み書きする仕組みを作る
  | ├─【Pythonの基礎知識】CSVを自在に扱う仕組みを作る
  | ├─【Pythonの基礎知識】JSONで構造化データを操る
  | └─【Pythonの基礎知識】例外処理で“壊れない仕組み”を設計する
  |
  └─STEP 5:Pythonで“自動化する仕組み”を作る(応用実践編)
    ├─【Pythonの基礎知識】スクリプトを自動実行させる仕組みを作る
    ├─【Pythonの基礎知識】日次タスクを自動化して人の時間を解放する
    ├─【Pythonの基礎知識】外部APIを活用して作業を外部化する
    └─【Pythonの基礎知識】ログを記録して仕組みの信頼性を高める

変数の基礎と値の結びつき

Pythonでプログラムを書くとき、変数と値の関係を正しく理解しているかどうかで、コードの安定性は大きく変わります。

変数は「値をしまう箱」ではなく、「値を指し示すラベル」です。

ここを誤解したまま進むと、意図しない動作やデータの上書きが起きる原因になります。

この記事では、実際のコードと具体的な会話例を交えながら、変数と値がどのように結びついて動いているのかを整理します。

変数って、ただ数字や文字を入れてるだけじゃないの?
そう見えるけれど、Pythonでは「変数は値そのものではなく、値(オブジェクト)を指している名前」なんです。

変数とは何か

Pythonで最初に登場する「変数」は、単に数字や文字を入れる箱のように思われがちです。

実際には、変数は「値(オブジェクト)を指す名前」であり、値そのものを直接持っているわけではありません。

この仕組みを理解しておくと、コードの動きを正確に読めるようになります。

変数って、100とか文字を“入れてる”イメージだったけど、違うの?
そう感じる人は多いです。でもPythonでは、変数は“入れ物”ではなく“ラベル”なんです。つまり、scoreという名前が「100というオブジェクトを指している」だけなんです。

実際の挙動を確かめてみましょう。次の手順を行います。

  1. ターミナルを開いて、Pythonのインタプリタ(対話モード)を起動します。

    python3

  2. 対話モードのプロンプト(>>>)が表示されたら、以下を入力します。

    >>> score = 100
    >> score

【出力例:】

100

このときPythonの内部では、「変数scoreが整数オブジェクト100を参照する」という関係が作られています。

もし同じ処理をスクリプトで確認したい場合は、ファイルに次のように書きます。

[ sample.py ]

score = 100
print(score)

そして、ターミナルで実行します。

python3 sample.py

【出力例:】

100

じゃあ、scoreって実際には100を“持ってる”んじゃなくて、“指してる”ってことか。
その通りです。この感覚を持てるようになると、Pythonの動作を表面的ではなく“仕組み”として理解できるようになります。

値(オブジェクト)との関係性

次に、変数と値(オブジェクト)の結びつきを見てみましょう。

a = [1, 2, 3]
b = a
b.append(4)

このコードを実行したあと、aとbの中身を確認してみます。

【出力例:】

>>> a [1, 2, 3, 4]
>> b [1, 2, 3, 4]

えっ、bに追加したのにaまで変わってる!
そうなんです。aとbは同じリストオブジェクトを参照しているため、どちらを変更しても影響が及びます。これが「ミュータブル(変更可能)なオブジェクト」を扱うときに起こる典型的な例です。

この関係を表で整理すると、より分かりやすくなります。

変数名参照先オブジェクト
a[1, 2, 3, 4]
baと同じオブジェクト

リストのようなミュータブルな型では、複数の変数が同じオブジェクトを共有していると、一方の操作がもう一方にも反映されます。

逆に、文字列や整数のようなイミュータブルな型では、再代入時に新しいオブジェクトが作られるため、影響は独立します。

つまり、「変数=名前」「値=オブジェクト」「関係=参照」って考えるといいのか!
その通りです。この考え方が身につくと、Pythonの動作を“感覚”ではなく“仕組み”として理解できるようになります。

変数の振る舞い:代入・再代入・参照

Pythonの変数は「箱」ではなく「ラベル」のように働きます。

この特徴を正しく理解しておくと、思い通りの結果を得られるだけでなく、バグを防ぐ力にもつながります。

ここでは、変数の代入・再代入・参照という3つの動きを通して、Pythonの内部で何が起きているのかを具体的に見ていきます。

同じように代入しているのに、結果が違うことがあるのはなぜ?
Pythonでは「どんな値を指しているか」が結果を左右します。見た目が同じでも、背後の“オブジェクト”が違えば動作も変わるんです。

代入によるバインディング

代入とは、変数名を値(オブジェクト)に結びつける操作のことです。

つまり、変数が「このオブジェクトを参照する」と宣言する行為です。

>>> x = 10
>>> y = x
>>> y

【出力例:】

10

このとき、x と y はどちらも同じ整数オブジェクト「10」を参照しています。

この仕組みを「バインディング(binding)」と呼びます。

xとyって別々に存在してるの?

それとも同じもの?

同じオブジェクトを参照しています。つまり、名前が2つあるだけで、中身(オブジェクト)はひとつなんです。

変数が値を「持つ」わけではなく、値を「指している」というイメージを持つと、Pythonの動作が一気に理解しやすくなります。

再代入と型の変化

次に、同じ変数に別の値を代入するとどうなるかを見てみましょう。

>>> x = 10
>>> x = "Python"
>>> x

【出力例:】

'Python'

最初に x は整数オブジェクト 10 を指していましたが、再代入後は文字列オブジェクト "Python" を指すようになりました。

つまり、x の「中身が変わった」のではなく、参照先が切り替わっただけです。

型が勝手に変わるって不安だけど、実際には安全なの?
Pythonは動的型付け言語なので、変数自体には型がありません。

型を持つのは“値(オブジェクト)”側なんです。

だから、変数がどんな値を指すかで動作が変わるんです。

この性質に慣れると、Pythonでは「どの変数がどのオブジェクトを参照しているか」を意識することが重要だと分かります。

参照とオブジェクトの共有

次に、複数の変数が同じオブジェクトを参照した場合の動きを確認してみましょう。

>>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> a

【出力例:】

[1, 2, 3, 4]

b に対して append() を実行したのに、a も同じように変化しています。

これは、a と b が同じリストオブジェクトを共有しているためです。

bだけ変えたつもりなのにaまで変わるのはびっくりだね。
リストや辞書のような“ミュータブル(変更可能)”なオブジェクトは共有されると、このような影響が出ます。

独立させたい場合は、コピーを作るのが安全です。

以下の表に、代入・再代入・参照の関係をまとめます。

操作変数の動き結果の特徴
代入名前がオブジェクトを指す変数と値が結びつく
再代入参照先が新しいオブジェクトに切り替わる元のオブジェクトは切り離される
参照共有複数の変数が同じオブジェクトを指す一方の変更が他方にも影響

これらの仕組みを理解しておくことで、「なぜこの変数が変わったのか」「どこで値が共有されたのか」を説明できるようになります。

変数の動きを正確にイメージできれば、コードの安定性が大きく上がります。

スコープとライフサイクルから見る変数の動き

Pythonでプログラムを書くうえで、変数がどこまで使えるのか、いつ消えるのかを理解しておくことはとても重要です。

スコープ(有効範囲)とライフサイクル(生存期間)を理解していないと、意図しない値の上書きや、思わぬエラーに悩まされることがあります。

ここでは、ローカル変数とグローバル変数の違い、そして変数がどのように生まれ、消えていくのかを、実例を通して整理していきます。

同じ名前の変数を関数の中と外で使うと、なぜか結果が違うんだけど?
それは変数の「スコープ」が関係しています。どこで定義されたかによって、見える範囲や扱われ方が変わるんです。

ローカル・グローバル変数の役割

Pythonでは、変数がどこで定義されたかによって有効範囲(スコープ)が異なります。

関数外で定義された変数はグローバル領域に、関数内で定義された変数はローカル領域に属します。

それぞれの扱い方を理解することで、思わぬバグを防ぐことができます。

Pythonはプログラムを実行するとき、最初にグローバル領域を1回だけ読み込んで評価します。

その後、関数が呼ばれるたびにローカル領域が一時的に生成され、処理が終わると消えます。

# -----------------------------------------
# ここがグローバル領域(global scope)
# -----------------------------------------
x = 10 # グローバル変数

def sample_function():
    # -----------------------------
    # ここがローカル領域(local scope)
    # -----------------------------
    y = 5 # ローカル変数
    print("関数内:", x, y)

sample_function()
print("関数外:", x) # 【出力例:】関数内: 10 5
              関数外: 10

ポイント

  • グローバル領域:関数やクラスの外側(x = 10 や sample_function() の呼び出し部分)
  • ローカル領域:関数の内部(y = 5 の定義部分)

グローバル領域とは?

プログラム全体の中で、関数やクラスの外側に書かれたコードが実行される範囲を「グローバル領域(global scope)」といいます。

ここで定義された変数は「グローバル変数」となり、モジュール内のどこからでも参照可能です。

message = "Hello"

def greet():
    message = "Hi"
    print(message)

greet()
print(message)

【出力例:】

Hi
Hello

この結果を見ると、関数内の message は「Hi」、関数外の message は「Hello」となっています。

同じ名前でも、関数の中と外で別のスコープを持っているため、それぞれ独立して扱われるのです。

同じ名前なのに別の変数扱いになるのはちょっとややこしいね。
確かに最初は混乱しますが、スコープを意識すれば思い通りに動かせます。たとえば、関数の中から外の変数を使いたいときは「global」を指定すればいいんです。

count = 0

def add():
    global count
    count += 1

add()
print(count)

【出力例:】

1

このように global を使うと、関数の外で定義された変数に直接アクセスできるようになります。ただし、どこからでも変更できてしまうため、複雑なプログラムでは混乱の原因にもなります。

そのため、基本はローカル変数を使い、必要なときだけグローバル変数を明示的に操作するのが安全です。

種類定義場所有効範囲注意点
ローカル変数関数内関数内のみ外部から参照できない
グローバル変数関数外プログラム全体関数から変更するには global が必要

ライフサイクルとガベージコレクションの関係

変数は、プログラムの中で「いつ生まれ、いつ消えるか」というライフサイクルを持っています。

スコープを抜けた変数は自動的に破棄され、Python内部のガベージコレクション(不要なメモリを回収する仕組み)によって整理されます。

def create_value():
    data = [1, 2, 3]
    print("関数内:", data)

create_value()
print("関数外で参照しようとするとエラー")

【出力例:】

関数内: [1, 2, 3]
Traceback (most recent call last):
    NameError: name 'data' is not defined

関数を抜けた瞬間に、data はスコープの外へ出て存在しなくなります。

このように、Pythonではスコープが切れた時点で不要な変数は自動的に破棄されるため、メモリ管理を意識せずに安全にプログラムを書けるのです。

実体験ケース:変数でつまずいたときの学び

Pythonを学び始めた頃、変数という言葉を何となく「値を入れる箱」として理解していました。

しかし実際にコードを書いていく中で、思いもよらない結果が出たり、意図した動作をしないことが多々ありました。

この体験から、単に「書き方」を覚えるのではなく、「仕組み」を理解することの重要さを痛感しました。

ここでは、私自身が変数でつまずいた具体的な経験と、そこから得た学びを共有します。

変数なんて簡単だと思ってたのに、動かしてみると結果が違うことが多くて混乱するんだよね。
実はそこにこそ、Pythonを深く理解する入り口があります。何が起きているのかを一度立ち止まって見直すと、考え方がガラッと変わります。

何をやったか:私の経験

最初の頃、私はリストを扱うコードで何度も同じ失敗を繰り返していました。 ある日、複数の変数に同じリストを代入して、それぞれ独立して扱えると思っていたのです。

a = [1, 2, 3]
b = a
b.append(4)
print(a)

【出力例:】

[1, 2, 3, 4]

b に変更を加えたのに、a まで変わってしまったのです。
「bに追加しただけなのに、なぜaまで変わるんだ?」と、本気で悩みました。

まさか同じリストを“共有”しているなんて、最初は思いもしなかったよね。
その通りです。Pythonでは変数が“同じオブジェクトを参照している”ということを理解していないと、こうした現象に必ずつまずきます。

どこで迷ったか・なぜ迷ったか

私は「変数は値をコピーして持つもの」というイメージに引きずられていました。

Pythonでは実際には「値を持つ」のではなく、「オブジェクトを参照する」構造になっているため、同じリストを別の変数が指すと、片方の変更がもう一方に反映されてしまいます。

id(a)
id(b)

【出力例:】

4389012800
4389012800

このように、a と b は同じオブジェクトIDを持っており、つまり同じ場所を参照しているのです。

この「参照」という概念を理解していなかったことが、私の混乱の根本原因でした。

“コピーじゃなくて参照”って言われても最初はピンと来なかったけど、id() で確認すると一気に腑に落ちるね。
そうなんです。実際にオブジェクトIDを見てみると、Pythonが何をしているのかがはっきり見えてきます。

そこから得た気づきと再発防止策

この経験から得た最大の気づきは、「Pythonの変数は“ラベル”にすぎない」ということです。

データそのものではなく、データを指す“名前”であるため、同じデータを指せば当然変化も共有されます。

import copy

a = [1, 2, 3]
b = copy.deepcopy(a)
b.append(4)
print(a)
print(b)

【出力例:】

[1, 2, 3]
[1, 2, 3, 4]

このように copy.deepcopy() を使うことで、リストを“別のオブジェクト”として複製できるようになりました。

これを知ってから、同じようなミスは一度も起きていません。

なるほど、変数の正体を理解してからは、コードの動きを予測できるようになったんだね。
そうですね。変数を「モノ」ではなく「関係」として捉えると、Pythonの仕組みが一気にクリアになります。それ以来、私はコードを書くたびに「これはどのオブジェクトを参照しているか?」を意識するようになりました。

変数の本質を理解することは、単なる文法知識ではなく、“思考の整理”でもあります。

Pythonの変数は、あなたの意図をそのまま形にしてくれる道具です。

仕組みを知ることで、プログラム全体を「意図通りに動かす力」が確実に身につきます。

まとめ

ここまでで、Pythonの変数がどのように「値」と結びつき、どんなタイミングで生成・消滅するのかを整理してきました。

一見するとシンプルな仕組みですが、その裏では「スコープ」と「ライフサイクル」という明確なルールが働いています。

これを理解しておくことで、予期せぬ動作を防ぎ、安定したコードを書けるようになります。

結局、変数って“ただの箱”じゃないってことなんだね。
そうです。Pythonの変数は「箱」ではなく「ラベル」のようなものです。どのオブジェクトを指しているかを理解できれば、プログラムの動きが見えるようになります。

スコープを意識して変数を定義すれば、思わぬ上書きや参照トラブルを防げます。

また、ライフサイクルを理解しておくことで、不要な変数を残さず、メモリの無駄をなくせます。

特に、ガベージコレクションの仕組みはPythonが自動で行ってくれるとはいえ、意図的に参照を切る意識を持つことが、安定した開発環境を作る鍵になります。

最後にもう一度整理します。

要点理解すべきポイント
スコープ変数の有効範囲を決める仕組み。ローカルとグローバルを正しく使い分ける。
ライフサイクル変数が生まれ、使われ、破棄されるまでの流れ。関数を抜けた時点でローカル変数は破棄される。
ガベージコレクション不要になったオブジェクトを自動で回収。参照が残らないように意識する。

理解が深まると、変数をただ使うのではなく、「生かす」ことができるようになります。

Pythonの変数はあなたの思考を映す鏡です。仕組みを知れば、コードも結果も驚くほどシンプルに見えるようになります。

次のおすすめ記事

よく読まれている記事

1

「私たちが日々利用しているスマートフォンやインターネット、そしてスーパーコンピュータやクラウドサービス――これらの多くがLinuxの力で動いていることをご存じですか? 無料で使えるだけでなく、高い柔軟 ...

2

Linux環境でよく目にする「Vim」という名前。サーバーにログインしたら突然Vimが開いてしまい、「どうやって入力するの?」「保存や終了ができない!」と困った経験をした人も多いのではないでしょうか。 ...

3

ネットワーク技術は現代のITインフラにおいて不可欠な要素となっています。しかし、ネットワークを深く理解するためには、その基本となる「プロトコル」と「レイヤ」の概念をしっかり把握することが重要です。 こ ...

4

この記事は、Linuxについて勉強している初心者の方向けに「Shellスクリプト」について解説します。最後まで読んで頂けましたら、Shellスクリプトはどのような役割を担っているのか?を理解出来るよう ...

5

Javaは世界中で広く使われているプログラミング言語であり、特に業務システムやWebアプリケーションの開発において欠かせない存在です。本記事では、初心者向けにJavaの基礎知識を網羅し、環境構築から基 ...

-Pythonの基礎知識(基礎編)