Skip to content
This page has been auto-translated and may contain errors.View in English

変数と型

すべてのプログラムは何かを記憶する必要があります。クイズにはプレイヤーの名前が必要です。ゲームには現在のスコアが必要です。天気スクリプトには確認したい都市が必要です。Pythonはこのために変数を使います。変数とは値に付ける名前のことで、プログラム全体を通して使用できます。

変数は値への名前付き参照です。Pythonは=の右側にあるオブジェクトに名前を束縛し、いつでも再束縛できます。型は名前ではなく値に存在します。

Pythonにおいて、変数は名前束縛です。つまり、実行時にオブジェクトに解決される名前空間内の参照です。型はオブジェクトが持つものであり、名前は持ちません。これが動的型付けです。同じ名前が異なるステートメント間で、まったく異なる型のオブジェクトを参照できます。

python
player_name = "さくら"
score       = 0
city        = "東京"

3行で3つのことをPythonが記憶します。後でこれらの名前を使えば、Pythonは値を返してくれます。

各行は束縛を作成します。左側の名前が右側のオブジェクトを参照します。Pythonはまず右辺を評価し、それから束縛を作成します。

各代入は現在のスコープのローカル名前空間に名前を作成するか再束縛します。Pythonは束縛が有効になる前に右辺の式を完全に評価します。名前自体には型情報が含まれません。

値を格納する

=記号は数学の授業から来る人のほぼ全員を戸惑わせます。Pythonでは、=は「等しい」という意味ではありません。この名前でこの値を格納するという意味です。左から右へ読みましょう:

python
city = "東京"

city"東京"が入ります。Pythonに「"東京"を記憶してcityというラベルを付けて」と伝えているわけです。

変数の値はいつでも置き換えられます。Pythonは最新のものを使います:

python
score = 0
score = 10   # score は今 10
score = 15   # score は今 15

=代入です。現在のスコープ内でオブジェクトに名前を束縛します。変数を更新する標準的な省略表現は拡張代入です:

python
score = 0
score += 10   # 同じ意味: score = score + 10
score *= 2    # 同じ意味: score = score * 2

複数の名前を一度に束縛することもできます:

python
x, y, z = 1, 2, 3
a = b = 0        # 両方ともゼロから始まる

代入は名前をオブジェクトに束縛します。コンテナに値をコピーするわけではありません。2つの名前が同じオブジェクトを参照できます:

python
a = "hello"
b = a
print(id(a) == id(b))   # True(メモリ上の同じオブジェクト)

b = "world"             # b が新しいオブジェクトに再束縛される
print(id(a) == id(b))   # False
print(a)                # まだ "hello": b の再束縛は a に影響しない

id()はオブジェクトの同一性(CPythonではメモリアドレス)を返します。名前束縛とコピーの違いは、後の章で扱うリストや辞書のようなミュータブルなオブジェクトでより重要になります。

型アノテーションは静的解析ツールのために期待される型を記述します。実行時には影響を与えません:

python
name:  str   = "さくら"
score: int   = 0
ratio: float = 0.85

変数の命名

名前は自分で選びます。Pythonにはいくつかの厳格なルールがあり、コミュニティは最初から採用する価値のある慣習に従っています。わかりやすい名前は数週間後でもコードを読みやすくします。意味不明な名前は苦痛を生みます。

Pythonは識別子の構文ルールを少数強制します。それ以外では、PEP 8の慣習がすべてのPythonコードベースとツールにおけるデファクトスタンダードです。

Pythonの識別子構文ルールは最小限です。PEP 8の慣習はインタープリタによって強制されませんが、リンター、型チェッカー、すべてのプロのPythonコードベースで前提とされています。これらから外れると摩擦が生じます。

Pythonが強制するルール:

  • 使えるのは文字、数字、アンダースコアのみ。スペースやハイフンは使えない
  • 文字またはアンダースコアで始まること。数字で始めることはできない
  • 大文字と小文字は区別される:scoreScoreSCOREはそれぞれ別の変数

全員が従う慣習(PEP 8):

対象スタイル
変数と関数snake_caseuser_name, total_price
定数UPPER_SNAKE_CASEMAX_RETRIES, BASE_URL
クラスPascalCaseUserAccount, DataLoader
python
# わかりやすい名前、一目でわかる
user_name    = "さくら"
total_price  = 49.99
is_logged_in = True
MAX_RETRIES  = 3

# 1時間以内に後悔する名前
x   = "さくら"
tp  = 49.99
b   = True

早めに知っておく価値のある落とし穴:listinputtypeprintのようなPythonの組み込みと同じ名前を変数に付けないでください。Pythonは許可しますが、そのスコープの残りの部分で組み込みが暗黙的に壊れ、結果として生じるエラーは追跡が困難です。

Pythonの組み込みをシャドウイングしないでください。listtypeinputprintstrへの代入は、警告なしにそのスコープの残りの部分で組み込みを上書きします。見つけるのが大変なサイレントバグです。

UPPER_SNAKE_CASEは慣習であり、強制されません。Pythonは後でMAX_RETRIES = 99と再代入することを止めません。他の開発者へのシグナルに過ぎません。

組み込みをシャドウイングすると、通常の名前解決順序で組み込みより優先されるローカル束縛が作成されます。組み込みはbuiltins.printなどを通じてアクセスできますが、シャドウイングされた名前が通常の使用時にそれを隠します。UPPER_SNAKE_CASEには言語レベルの強制はありません。ツールが確認できる真のイミュータビリティ保証には、アノテーション内のtyping.Finalが標準的なアプローチです。

格納できるもの

ほぼすべてのプログラムで使う4つの型があります。Pythonは値の書き方からどの型を意味するか判断します。型を明示的に宣言する必要はありません。

Pythonはリテラルの構文から型を推論します。この4つの型は基本的な値の空間をカバーし、言語内の他のすべてはこれらの上に構築されています。

Pythonの4つの基本型はそれぞれ、異なるメモリレイアウト、精度特性、演算セマンティクスを持つ異なるランタイムオブジェクトに対応します。型は名前ではなくオブジェクトによって決まります。

テキスト(str

テキストはシングルクォートまたはダブルクォートの中に入れます。クォートはPythonに対して、変数名ではなくリテラルの文字であることを伝えます。一度作成された文字列はその場で変更できません。文字列の章ではできることをすべて解説します。

python
player_name = "さくら"
city        = "東京"
message     = 'ゲームオーバー'

テキストにアポストロフィが含まれる場合、エスケープを避けるためにダブルクォートを使います:

python
note = "It's a great day"
note = 'It\'s a great day'   # 同じ結果、エスケープを使用

文字列はシングルまたはダブルクォート内の任意のテキストを保持します。イミュータブルです。どの操作も文字列をその場で変更しません。すべての変換は新しい文字列を返します。これはパフォーマンスに影響します。ループ内で繰り返し+を使うと、毎ステップで新しい文字列オブジェクトが作成されます。効率的な代替方法は文字列の章で解説します。

python
player_name = "さくら"
city        = "東京"
note        = "It's a great day"

strはバイトではなくUnicodeコードポイントのイミュータブルなシーケンスです。len("café")は5ではなく4です。イミュータビリティにより文字列はハッシュ可能で、辞書のキーやセットのメンバーとして有効です。CPythonは識別子のように見える短い文字列をインターンします。同じ短いリテラルが割り当てられた2つの変数は、メモリ上で単一のオブジェクトを共有することがよくあります。どちらのクォートスタイルでも同一のオブジェクトが作成されます。

python
player_name = "さくら"
city        = "東京"
note        = "It's a great day"

整数(int

整数はクォートや小数点なしで記述します。Pythonはこれを整数と呼びます。必要なだけ大きな値を使えます。Pythonは特別な作業なしで任意の大きな数値を処理します。

python
score      = 0
age        = 28
population = 8_100_000_000   # アンダースコアは読みやすさのためだけ

整数はクォートや小数点なしで記述します。Pythonの整数は任意精度です。CやJavaの32ビットまたは64ビットの固定サイズ整数とは異なり、任意の値を保持するために拡張されます。数値リテラル内のアンダースコアは装飾的なもので、Pythonには無視されます。

python
score      = 0
age        = 28
population = 8_100_000_000

Pythonのintは任意精度です。値が大きくなるにつれてオブジェクトが追加メモリを割り当て、使用可能なRAMによってのみ制限されます。CPythonは-5から256の小さな整数をシングルトンとしてキャッシュします。id(1) == id(1)は常にTrueです。その範囲外では、各リテラルが別個のオブジェクトを作成します。これが整数の比較でisが信頼できない結果をもたらす理由です。常に==を使ってください。

python
score      = 0
age        = 28
population = 8_100_000_000

小数(float

小数点を含む数値はすべて浮動小数点数です。ほとんどの計算で期待通りに動作します。知っておくべき点:一部の小数値はバイナリで正確に格納できないため、わずかな丸め誤差が生じることがあります:

python
price       = 4.99
temperature = 36.6

0.1 + 0.2   # 0.30000000000000004

日常的な作業ではほとんど問題ありません。1セントの端数が重要な金融計算には、正確に処理できるdecimalモジュールがあります。数値の章で解説します。

小数点を含む数値はすべてfloatになります。PythonのフロートはIEEE 754 binary64:64ビットで約15〜17桁の有効十進数精度です。よく知られた問題:0.1 + 0.20.30000000000000004です。Pythonのバグではなく、バイナリ表現の結果です。正確な小数が重要な金融計算には、Pythonのdecimalモジュールが適切なツールで、数値の章で解説します。

python
price       = 4.99
temperature = 36.6

floatはCのdoubleに対応します:IEEE 754 binary64、53ビット仮数、相対精度2^-52 ≈ 2.2e-16。2以外の素因数を持つ分母の分数(例:1/10 = 1/(2×5))はバイナリで無限小数になり、正確に格納できません。正確な小数演算にはPythonのdecimal.Decimalが任意精度の10進数を使用します。正確な有理数演算にはfractions.Fractionが分子と分母のペアを格納します。どちらも標準ライブラリにあり、モジュールの章で解説します。

python
price       = 4.99
temperature = 36.6

真偽値(bool

単純にオンかオフかのものがあります。Pythonはこれにブール値を使います:TrueFalseの2つの値だけです。この段階では些細に見えますが、プログラム内のすべての条件と分岐はブール値で動きます。

python
is_logged_in = True
has_errors   = False

Pythonは条件で使われるとFalseのように扱われる値もあります:00.0""、そしてNone(Pythonの「値なし」)はすべてFalseのように振る舞います。それ以外はすべてTrueのように振る舞います。これは制御フローの章で役立ちます。

boolTrueまたはFalseのみを保持します。比較によって返され、条件によって消費されます。Pythonにはより広い真値偽値のセットがあります:ゼロ値、空のコンテナ、Noneは偽値で、それ以外はすべて真値です。有用な細かい点:boolintのサブクラスなので、True + True2に評価されます。

python
is_logged_in = True
has_errors   = False

boolintをサブクラス化します。TrueFalseはそれぞれ整数値1と0を持つシングルトンです。偽値:ゼロ値(00.0)、空のシーケンスとマッピング(""[](){})、NoneFalse。それ以外はすべて真値です。カスタムオブジェクトは__bool__または__len__を通じてこれを制御します。isinstance(True, int)Trueで、これはジェネリックな型チェックコードで重要です。

python
is_logged_in = True
has_errors   = False

型の確認と変換

値の型がわからない場合、type()が教えてくれます。値が特定の型かどうかを確認するには、isinstance()がより信頼できるツールです:

python
print(type("hello"))   # <class 'str'>
print(type(42))        # <class 'int'>
print(type(3.14))      # <class 'float'>
print(type(True))      # <class 'bool'>

isinstance(42, int)    # True
isinstance("hi", str)  # True

type()はオブジェクトの正確な型を返します。自分のコードで型チェックを行う場合、isinstance()が推奨されます。継承を処理できますが、type()の比較はそれができません。

python
print(type(42))          # <class 'int'>
isinstance(True, int)    # True(bool は int のサブクラス)
type(True) == int        # False(完全一致のみ、サブクラスなし)

type(x)xの型オブジェクトを返します。isinstance(x, T)はMRO(x.__class__.__mro__)を辿り、type()の比較が見逃すサブクラス関係を処理します。実用的なケース:isinstance(True, int)Trueboolintをサブクラス化するため)、type(True) == intFalse(完全な同一性チェックのため)。プロダクションコードの型ガードにはisinstance()を使ってください。

python
isinstance(True, int)    # True
type(True) == int        # False

Pythonは型を自動的に混在させません。文字列と数値を連結するとTypeErrorが発生します:

python
score = 42
print("あなたのスコアは " + score)        # TypeError
print("あなたのスコアは " + str(score))   # 動作する

型名を関数として使って明示的に変換します:

呼び出し結果
str(42)"42"
int(3.9)3(切り捨て、四捨五入ではない)
float("3.14")3.14
int("3.14")ValueError:小数文字列を直接intに変換できない
int(float("3.14"))3(まずfloatに変換してからintに変換)
bool(0) / bool("")False

実践

4つの型すべてが小さなスクリプトで一緒に動作しています。出力行はf文字列を使ってテキストに値を埋め込んでいます。開きクォートの前にfを付け、変数を{}で囲みます。Pythonはそれを変数の実際の値に置き換えます。次の章で正しく学びます。

python
player_name = "さくら"
level       = 3
accuracy    = 0.94
is_premium  = True

print(f"{player_name} はレベル {level} で精度 {accuracy:.0%} です。")
print(f"プレミアムアカウント: {is_premium}")

型が重要なのは、level + 1は動作してもplayer_name + 1は動作しないからです。各変数は一種類のものだけを保持します。Pythonは暗黙的に混在させてくれません。

4つの型すべてを使ったリアルな設定ブロックで、定数と実行時の状態を分けています。f"..."構文はf文字列です。{}内の任意の式が実行時に評価され、出力に埋め込まれます。出力と入力の章で詳しく解説します。

python
BASE_URL    = "https://api.example.com"
MAX_RETRIES = 3
DEBUG       = False

user_name     = "さくら"
request_count = 0
last_response = None

request_count += 1
print(f"[{request_count}] {BASE_URL} | debug={DEBUG}")

Noneは「まだ値がない」ための標準的なプレースホルダーです。型はNoneTypeで、条件では偽値として振る舞います。プログラムの後半まで意味を持たない変数のデフォルトとして使ってください。

同じ設定にインライン型アノテーションを付けたものです。アノテーションは型チェッカーとIDEのためのドキュメントで、実行時には影響を与えません:

python
BASE_URL:    str  = "https://api.example.com"
MAX_RETRIES: int  = 3
DEBUG:       bool = False

user_name:     str        = "さくら"
request_count: int        = 0
last_response: str | None = None

str | NoneはPython 3.10からのユニオン構文です。変数が文字列またはNoneのいずれかを保持することを表します。それ以前のバージョンでは、typingモジュールのOptional[str]が同等です。最小バージョンが許す場合、現代のPythonではstr | None形式が推奨されます。