Python チートシート
Python 3 を前提とした、学習・業務・説明用の早見表です。
「何か」「どう使うか」「他の人へどう説明するか」を短く確認できます。
目次
- 基本用語とデータ型一覧
- 数値型:int・float
- 文字列:str
- リスト:list
- タプル:tuple
- 辞書:dict
- 集合:set
- 日付と時刻:date・datetime
- オブジェクト指向
__init__と__main__の違い- 継承・オーバーライド・多重継承
- コールスタック・スタックトレース
- 例外処理
- 説明用まとめ
1. 基本用語とデータ型一覧
変数・オブジェクト・型
name = "Cake"
age = 40
print(type(name)) # <class 'str'>
print(isinstance(age, int)) # True
- 変数:オブジェクトを参照するための名前
- オブジェクト:値と振る舞いを持つ実体
- 型:そのオブジェクトが扱える値や操作の種類
Pythonでは「変数の箱に値が入る」というより、変数名がオブジェクトを参照すると考えると正確です。
主なデータ型
| 型 | 読み方・正式名 | 例 | 特徴 | 変更可能か |
|---|---|---|---|---|
int |
イント/integer(インテジャー) |
10, -3
|
整数 | 不可 |
float |
フロート/floating point(フローティング・ポイント) | 3.14 |
小数・浮動小数点数 | 不可 |
bool |
ブール/boolean(ブーリアン) |
True, False
|
真偽値 | 不可 |
str |
ストリング/string(ストリング) | "Python" |
文字列 | 不可 |
list |
リスト | [1, 2, 3] |
順序あり・重複可 | 可 |
tuple |
タプル | (1, 2, 3) |
順序あり・重複可 | 不可 |
dict |
ディクト/dictionary(ディクショナリ) | {"name": "Cake"} |
キーと値の組 | 可 |
set |
セット | {1, 2, 3} |
重複なしの集合 | 可 |
NoneType |
ノンタイプ | None |
値がないことを表す | 不可 |
date |
デート | date(2026, 7, 22) |
日付 | 不可 |
datetime |
デートタイム | datetime(2026, 7, 22, 10, 30) |
日付と時刻 | 不可 |
- ミュータブル(mutable/ミュータブル):作成後に中身を変更できる
- イミュータブル(immutable/イミュータブル):作成後に中身を変更できない
型変換
int("100") # 100
float("3.14") # 3.14
str(100) # "100"
list("abc") # ["a", "b", "c"]
tuple([1, 2]) # (1, 2)
set([1, 1, 2]) # {1, 2}
2. 数値型:int・float
基本演算
10 + 3 # 13 加算
10 - 3 # 7 減算
10 * 3 # 30 乗算
10 / 3 # 3.333... 除算。結果は基本的にfloat
10 // 3 # 3 切り下げ除算
10 % 3 # 1 余り
10 ** 3 # 1000 べき乗
よく使う関数
abs(-10) # 10
round(3.14159, 2) # 3.14
min(3, 8, 1) # 1
max(3, 8, 1) # 8
sum([10, 20, 30]) # 60
float の注意
0.1 + 0.2 # 0.30000000000000004 になる場合がある
float は2進数で小数を近似して保持するため、誤差が発生します。金額を厳密に扱う場合は、整数の円単位または Decimal(デシマル)を検討します。
from decimal import Decimal
price = Decimal("0.1") + Decimal("0.2")
print(price) # 0.3
説明するときの一言:
int は整数、float は小数を扱う型です。float には計算誤差があるため、金額などでは注意します。
3. 文字列:str
作成・参照・スライス
text = "Python"
text[0] # "P"
text[-1] # "n"
text[1:4] # "yth"
text[:3] # "Pyt"
text[3:] # "hon"
text[::-1] # "nohtyP"
len(text) # 6
文字列はイミュータブルなので、特定位置の文字を直接変更できません。
# text[0] = "J" # TypeError
text = "J" + text[1:] # "Jython"
よく使う操作
| 目的 | コード | 補足 |
|---|---|---|
| 前後の空白を除く | text.strip() |
左だけは lstrip()、右だけは rstrip()
|
| 置換する | text.replace("a", "b") |
元の文字列は変わらず、新しい文字列を返す |
| 分割する | text.split(",") |
戻り値はリスト |
| 結合する | ",".join(words) |
文字列のリストを結合 |
| 含まれるか調べる | "Py" in text |
True / False
|
| 位置を探す | text.find("th") |
なければ -1
|
| 位置を探す | text.index("th") |
なければ ValueError
|
| 個数を数える | text.count("a") |
一致数を返す |
| 大文字にする | text.upper() |
例:PYTHON
|
| 小文字にする | text.lower() |
例:python
|
| 先頭だけ大文字 | text.capitalize() |
例:Python
|
| 前方一致 | text.startswith("Py") |
True / False
|
| 後方一致 | text.endswith("on") |
True / False
|
| 数字だけか | text.isdigit() |
True / False
|
| 英数字だけか | text.isalnum() |
True / False
|
f文字列
name = "Cake"
price = 1200
message = f"{name}さんの商品価格は{price:,}円です"
# Cakeさんの商品価格は1,200円です
説明するときの一言:
str は文字列型です。添字やスライスで一部を取得できますが、元の文字列自体は直接変更できません。
4. リスト:list
リストは、順序を保ちながら複数の値をまとめ、後から変更できる型です。異なる型を混在させることもできます。
items = ["apple", "banana", "orange"]
empty = []
4-1. 参照・スライス
items[0] # "apple"
items[-1] # "orange"
items[1:3] # ["banana", "orange"]
items[:2] # ["apple", "banana"]
items[::2] # 1つ飛ばし
items[::-1] # 逆順の新しいリスト
len(items) # 要素数
存在しない位置を items[99] のように指定すると IndexError(インデックスエラー)になります。
4-2. 追加・結合
| 操作 | コード | 動作 |
|---|---|---|
| 末尾へ1要素追加 | items.append("grape") |
渡した値を1要素として追加 |
| 複数要素を追加 | items.extend(["grape", "melon"]) |
各要素を展開して追加 |
| 指定位置へ追加 | items.insert(1, "grape") |
位置1へ挿入 |
| 新しいリストを作る | items + ["grape"] |
元のリストは変えない |
| 繰り返す | [0] * 3 |
[0, 0, 0] |
items = ["apple"]
items.append(["banana", "orange"])
# ["apple", ["banana", "orange"]]
items = ["apple"]
items.extend(["banana", "orange"])
# ["apple", "banana", "orange"]
append() は「1つとして追加」、extend() は「中身を展開して追加」です。
4-3. 更新
items = ["apple", "banana", "orange"]
items[1] = "melon"
# ["apple", "melon", "orange"]
items[0:2] = ["grape", "peach"]
# ["grape", "peach", "orange"]
4-4. 削除
| 操作 | コード | 動作・注意 |
|---|---|---|
| 値を指定して削除 | items.remove("banana") |
最初に一致した1件を削除。なければ ValueError
|
| 位置を指定して削除 | items.pop(1) |
削除した値を返す |
| 末尾を削除 | items.pop() |
最後の値を返す |
| 位置・範囲を削除 |
del items[1] / del items[1:3]
|
戻り値なし |
| 全件削除 | items.clear() |
空リストにする |
安全に値を削除する例:
if "banana" in items:
items.remove("banana")
4-5. 検索・集計
"apple" in items # 含まれるか
"apple" not in items # 含まれないか
items.index("apple") # 最初の位置。なければValueError
items.count("apple") # 個数
len(items) # 要素数
min([3, 1, 8]) # 1
max([3, 1, 8]) # 8
sum([3, 1, 8]) # 12
4-6. 並べ替え
numbers = [3, 1, 10, 2]
numbers.sort() # 元のリストを昇順に変更
numbers.sort(reverse=True) # 元のリストを降順に変更
new_numbers = sorted(numbers) # 新しいリストを返す
numbers.reverse() # 現在の並びを逆転
users = [
{"name": "Cake", "age": 40},
{"name": "Cookie", "age": 20},
]
users.sort(key=lambda user: user["age"])
-
list.sort():元のリストを変更し、戻り値はNone -
sorted():元のデータを変更せず、新しいリストを返す
4-7. 繰り返し処理
for item in items:
print(item)
for index, item in enumerate(items):
print(index, item)
enumerate(エニュメレート)は、位置と値を同時に取得します。
names = ["Cake", "Cookie"]
ages = [40, 25]
for name, age in zip(names, ages):
print(name, age)
zip(ジップ)は、複数の反復可能オブジェクトを同じ位置ごとに組み合わせます。
4-8. リスト内包表記
numbers = [1, 2, 3, 4, 5]
squares = [number ** 2 for number in numbers]
# [1, 4, 9, 16, 25]
even_squares = [number ** 2 for number in numbers if number % 2 == 0]
# [4, 16]
基本形:
[変換後の値 for 要素 in 元データ if 条件]
複雑になりすぎる場合は、通常の for 文の方が読みやすくなります。
4-9. コピーの注意
a = [1, 2, 3]
b = a
b.append(4)
print(a) # [1, 2, 3, 4]
b = a はコピーではなく、同じリストを参照します。
a = [1, 2, 3]
b = a.copy() # または a[:]、list(a)
b.append(4)
print(a) # [1, 2, 3]
入れ子のリストを完全に分けたい場合は、ディープコピーを使います。
from copy import deepcopy
original = [[1, 2], [3, 4]]
copied = deepcopy(original)
-
copy():シャローコピー(shallow copy/シャローコピー)。外側だけ別物 -
deepcopy():ディープコピー(deep copy/ディープコピー)。内側も再帰的に別物
4-10. リスト操作の注意点
反復中に元のリストを変更しない
numbers = [1, 2, 3, 4]
# 新しいリストを作る方が安全
numbers = [number for number in numbers if number % 2 == 0]
入れ子リストの初期化
# 注意:3行が同じ内側リストを参照する
bad = [[0] * 3] * 3
bad[0][0] = 1
# [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
# 各行を別々に作る
safe = [[0] * 3 for _ in range(3)]
スタックとキュー
stack = []
stack.append("A")
stack.append("B")
stack.pop() # "B"
リストはスタックに使えます。先頭から頻繁に削除するキューでは、collections.deque(デック)が効率的です。
from collections import deque
queue = deque(["A", "B"])
queue.append("C")
queue.popleft() # "A"
説明するときの一言:
リストは、順序のある複数の値を保持し、追加・更新・削除できる可変コレクションです。
5. タプル:tuple
タプルは、順序を保つが、作成後に中身を変更できない型です。
point = (10, 20)
empty = ()
single = (10,) # 1要素では末尾のカンマが必要
主な操作
point[0] # 10
point[0:2] # (10, 20)
len(point) # 2
point.count(10) # 1
point.index(20) # 1
アンパック
x, y = (10, 20)
first, *middle, last = (1, 2, 3, 4)
# first = 1, middle = [2, 3], last = 4
x, y = y, x # 値の入れ替え
利用場面
- 変更されたくない値の組
- 関数から複数の値を返す
- 辞書のキーとして使う
- 座標やRGB値など、意味のまとまりを表す
タプルの各要素も辞書のキーにできる型である必要があります。リストを含むタプルはキーにできません。
説明するときの一言:
タプルは、リストに似ていますが、作成後に中身を変更できないため、固定した値の組に向いています。
6. 辞書:dict
辞書は、キー(key/キー)と値(value/バリュー)を対応づけて管理する型です。
user = {
"name": "Cake",
"age": 40,
"skills": ["Python", "Java"],
}
empty = {}
Python 3.7以降、辞書は挿入順を保持します。ただし、位置番号ではなくキーで値を扱うのが基本です。
6-1. 取得
user["name"] # "Cake"
user.get("age") # 40
user.get("email") # None
user.get("email", "未登録") # "未登録"
| 書き方 | キーがない場合 |
|---|---|
user["email"] |
KeyError(キーエラー) |
user.get("email") |
None |
user.get("email", "未登録") |
指定した既定値 |
値が None なのか、キー自体がないのかを区別したい場合は in を使います。
if "email" in user:
print(user["email"])
6-2. 追加・更新・結合
user["email"] = "Cake@example.com" # 新規追加
user["age"] = 39 # 更新
user.update({"age": 50, "city": "Tokyo"})
Python 3.9以降は | で新しい辞書を作れます。
base = {"name": "Cake", "age": 40}
extra = {"age": 50, "city": "Tokyo"}
merged = base | extra
# 同じキーは右側の値が優先される
元の辞書を更新する場合:
base |= extra
6-3. キーがない場合だけ初期値を入れる
user.setdefault("role", "member")
setdefault()(セットデフォルト)は、キーがあれば既存値を返し、なければ指定値を登録して返します。
groups = {}
for name, team in [("Cake", "A"), ("Cookie", "B"), ("Ice", "A")]:
groups.setdefault(team, []).append(name)
# {"A": ["Cake", "Ice"], "B": ["Cookie"]}
6-4. 削除
| 操作 | コード | 動作・注意 |
|---|---|---|
| キーを指定して削除 | del user["age"] |
なければ KeyError
|
| 削除して値を取得 | user.pop("age") |
なければ KeyError
|
| 既定値つきで削除 | user.pop("age", None) |
なければ既定値 |
| 最後の組を削除 | user.popitem() |
(キー, 値) を返す |
| 全件削除 | user.clear() |
空辞書にする |
6-5. キー・値・組の取得
user.keys() # キーのビュー
user.values() # 値のビュー
user.items() # (キー, 値)のビュー
これらはリストではなく、辞書の変更を反映するビューオブジェクトです。リストが必要なら変換します。
keys = list(user.keys())
6-6. 繰り返し処理
# キーを取得
for key in user:
print(key)
# 値を取得
for value in user.values():
print(value)
# キーと値を取得
for key, value in user.items():
print(key, value)
6-7. 検索・件数
"name" in user # キーに存在するか
"Cake" in user.values() # 値に存在するか
len(user) # キーと値の組の数
in user は、値ではなくキーを検索します。
6-8. 辞書内包表記
numbers = [1, 2, 3, 4]
squares = {number: number ** 2 for number in numbers}
# {1: 1, 2: 4, 3: 9, 4: 16}
even_squares = {
number: number ** 2
for number in numbers
if number % 2 == 0
}
# {2: 4, 4: 16}
基本形:
{キー: 値 for 要素 in 元データ if 条件}
6-9. 並べ替え
辞書自体ではなく、キーまたは (キー, 値) を並べ替えます。
scores = {"Cake": 80, "Cookie": 95, "Ice": 70}
sorted(scores) # キーで昇順
sorted(scores.items()) # キーで昇順
sorted(scores.items(), key=lambda item: item[1])
sorted(scores.items(), key=lambda item: item[1], reverse=True)
並べ替えた辞書を作る例:
sorted_scores = dict(
sorted(scores.items(), key=lambda item: item[1], reverse=True)
)
6-10. 入れ子の辞書
user = {
"name": "Cake",
"address": {
"prefecture": "Tokyo",
"city": "Shinjuku",
},
}
city = user["address"]["city"]
キーがない可能性を考慮する例:
city = user.get("address", {}).get("city", "未登録")
6-11. 辞書のキーにできるもの
キーには、基本的にハッシュ可能(hashable/ハッシャブル)な変更不能オブジェクトを使います。
使える例:
mapping = {
"name": "Cake", # str
1: "one", # int
(10, 20): "point", # tuple
}
使えない例:
# {[1, 2]: "value"} # listは変更可能なのでTypeError
# {{"a": 1}: "value"} # dictもキーにできない
- キーは重複できない
- 同じキーを再登録すると、後の値で上書きされる
- 値は重複してよい
6-12. コピーの注意
original = {"name": "Cake", "skills": ["Python"]}
shallow = original.copy()
shallow["skills"].append("Java")
print(original["skills"]) # ["Python", "Java"]
dict.copy() はシャローコピーなので、入れ子のリストや辞書は共有されます。
from copy import deepcopy
copied = deepcopy(original)
6-13. よく使う補助クラス
defaultdict(デフォルトディクト)
キーがない場合の初期値を自動生成します。
from collections import defaultdict
groups = defaultdict(list)
groups["A"].append("Cake")
groups["A"].append("Ice")
Counter(カウンター)
要素の出現回数を数えます。
from collections import Counter
counts = Counter(["apple", "apple", "banana"])
print(counts["apple"]) # 2
print(counts.most_common(1))
6-14. 辞書操作の注意点
反復中にキー数を変更しない
scores = {"Cake": 80, "Cookie": 40, "Ice": 70}
for name in list(scores):
if scores[name] < 60:
del scores[name]
fromkeys() と変更可能な初期値
keys = ["A", "B"]
bad = dict.fromkeys(keys, [])
bad["A"].append(1)
print(bad) # {"A": [1], "B": [1]}
同じリストが共有されるため、個別に作る場合は内包表記を使います。
safe = {key: [] for key in keys}
一言:
辞書は、名前やIDなどのキーを使って値を管理する可変コレクションです。位置ではなく、意味のあるキーで値を取得できます。
7. 集合:set
集合は、重複しない値をまとめる型です。順序や添字での参照を目的には使いません。
numbers = {1, 2, 3}
empty = set() # {} は空の辞書になる
主な操作
numbers.add(4) # 1要素追加
numbers.update([4, 5]) # 複数追加
numbers.remove(3) # なければKeyError
numbers.discard(99) # なくてもエラーにならない
numbers.pop() # 任意の1要素を削除して返す
numbers.clear() # 全件削除
集合演算
a = {1, 2, 3}
b = {3, 4, 5}
a | b # 和集合 {1, 2, 3, 4, 5}
a & b # 積集合 {3}
a - b # 差集合 {1, 2}
a ^ b # 対称差 {1, 2, 4, 5}
a <= b # 部分集合か
a >= b # 上位集合か
リストから重複を除く例:
unique_numbers = list(set([1, 1, 2, 3]))
元の順序を保って重複を除く場合は
list(dict.fromkeys(values))を使えます。
8. 日付と時刻:date・datetime
datetime(デートタイム)は、標準ライブラリのモジュール名であり、その中のクラス名でもあります。
from datetime import date, datetime, timedelta
-
date:日付だけ -
datetime:日付と時刻 -
timedelta(タイムデルタ):時間差・期間
作成・現在日時
today = date.today()
now = datetime.now()
birthday = date(1990, 4, 1)
meeting = datetime(2026, 7, 20, 10, 30)
各要素の取得
meeting.year # 2026
meeting.month # 7
meeting.day # 20
meeting.hour # 10
meeting.minute # 30
meeting.weekday() # 月曜=0 ~ 日曜=6
文字列へ変換:strftime
strftime(ストラフタイム)は、日時を指定形式の文字列へ変換します。
text = meeting.strftime("%Y-%m-%d %H:%M")
# "2026-07-20 10:30"
文字列から変換:strptime
strptime(ストリップタイム)は、文字列を日時へ変換します。
meeting = datetime.strptime("2026-07-20 10:30", "%Y-%m-%d %H:%M")
主な書式
| 記号 | 意味 | 例 |
|---|---|---|
%Y |
4桁の年 | 2026 |
%m |
2桁の月 | 07 |
%d |
2桁の日 | 20 |
%H |
24時間表記の時 | 10 |
%M |
分 | 30 |
%S |
秒 | 05 |
加算・減算・比較
tomorrow = today + timedelta(days=1)
one_hour_later = now + timedelta(hours=1)
start = datetime(2026, 7, 20, 10, 0)
end = datetime(2026, 7, 20, 12, 30)
difference = end - start
print(difference.total_seconds()) # 9000.0
if start < end:
print("startの方が先")
タイムゾーン
from datetime import datetime
from zoneinfo import ZoneInfo
jst_now = datetime.now(ZoneInfo("Asia/Tokyo"))
- ナイーブ(naive/ナイーブ):タイムゾーン情報なし
- アウェア(aware/アウェア):タイムゾーン情報あり
タイムゾーンあり・なしの datetime を混在させて比較しないようにします。
一言:
date は日付、datetime は日付と時刻、timedelta はその差や期間を扱います。
9. オブジェクト指向
OOP(オー・オー・ピー/Object-Oriented Programming:オブジェクト指向プログラミング)は、データと、そのデータを操作する処理をオブジェクトとしてまとめる考え方です。
クラスとインスタンス
- クラス:設計図・型
- インスタンス:クラスから生成された具体的な実体
class Product:
tax_rate = 0.10 # クラス変数
def __init__(self, name, price):
self.name = name # インスタンス変数
self.price = price # インスタンス変数
def total_price(self): # インスタンスメソッド
return round(self.price * (1 + self.tax_rate))
book = Product("Python入門", 2000) # インスタンス生成
print(book.name) # Python入門
print(book.total_price()) # 2200
変数の種類
| 種類 | 例 | 有効範囲・特徴 |
|---|---|---|
| ローカル変数 | total = 100 |
関数・メソッド内で使う |
| インスタンス変数 | self.name |
インスタンスごとに異なる値を持つ |
| クラス変数 | Product.tax_rate |
クラス全体で共有する |
リストなどの変更可能な値をクラス変数にすると、全インスタンスで共有されるため注意します。
メソッドの種類
class Product:
category = "book"
def __init__(self, name):
self.name = name
def display_name(self):
# インスタンスメソッド:selfで個別データを扱う
return self.name
@classmethod
def category_name(cls):
# クラスメソッド:clsでクラスを扱う
return cls.category
@staticmethod
def is_valid_name(name):
# スタティックメソッド:selfもclsも不要
return bool(name.strip())
-
self(セルフ):そのメソッドを呼び出したインスタンス -
cls(クラス):そのメソッドを呼び出したクラス
オブジェクト指向の三要素
| 要素 | 読み方 | 意味 | 主な効果 |
|---|---|---|---|
| カプセル化 | encapsulation(エンカプセレーション) | データと処理をまとめ、内部の扱いを制御する | 変更箇所を限定し、不正な状態を防ぐ |
| 継承 | inheritance(インヘリタンス) | 既存クラスの性質を引き継ぐ | 共通化・再利用・拡張 |
| ポリモーフィズム | polymorphism(ポリモーフィズム)/多態性 | 同じ呼び出し方で、対象ごとに異なる処理を行う | 呼び出し側の分岐を減らす |
資料によっては「抽象化」を含めて四大要素と説明する場合もありますが、ここでは、参考書などでよく使われる三要素で整理しています。
1. カプセル化
class BankAccount:
def __init__(self, balance):
self._balance = balance # 外部から直接変更しないという慣例
@property
def balance(self):
return self._balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("入金額は1円以上にしてください")
self._balance += amount
Pythonの _name は「外部から直接使わない」という慣例です。完全なアクセス禁止ではありません。
2. 継承
既存クラスの共通機能を、別のクラスへ引き継ぎます。
3. ポリモーフィズム
class Dog:
def speak(self):
return "ワン"
class Cat:
def speak(self):
return "ニャー"
for animal in [Dog(), Cat()]:
print(animal.speak())
呼び出し側はどの動物かを細かく分岐せず、共通して speak() を呼べます。
説明するときの一言:
オブジェクト指向は、関連するデータと処理をクラスにまとめ、実体であるインスタンスを作って扱う設計方法です。
10. __init__ と __main__ 形は似てるけど
両方とも前後に二重アンダースコアがつきますが、役割はまったく異なります。
| 項目 | 読み方 | 正体 | 役割 |
|---|---|---|---|
__init__ |
ダンダー・イニット | 特殊メソッド | インスタンスの初期値を設定する |
__main__ |
ダンダー・メイン | 実行中モジュールの特別な名前 | 直接実行されたファイルを示す |
dunder(ダンダー)は、double underscore(ダブル・アンダースコア)の略称です。
__init__
class User:
def __init__(self, name):
self.name = name
user = User("Cake")
-
User(...)でインスタンスを作るときに呼ばれる - インスタンス変数の初期値を設定する
- 厳密には、インスタンスを作るのは
__new__、初期化するのが__init__ -
__init__は値を返さない。returnで値を返すとTypeError
__init__.py との違い
__init__.py は、ディレクトリをPythonパッケージとして扱う際に使われるファイルです。クラスの __init__ メソッドとは別物です。
__main__
def main():
print("処理開始")
if __name__ == "__main__":
main()
- ファイルを直接実行した場合:
__name__は"__main__" - 他のファイルからインポートされた場合:
__name__はモジュール名 - インポート時にだけ実行したくない処理を分けられる
-
main()という関数名自体は慣例であり、Pythonで必須ではない
例:
# sample.py を直接実行
python sample.py
# このとき、sample.py 内では __name__ == "__main__"
# 別ファイルから読み込む
import sample
print(sample.__name__) # "sample"
一言:
__init__ はインスタンスの初期化処理、__main__ はファイルが直接実行されたかを判定するための特別なモジュール名です。
11. 継承・オーバーライド・多重継承
スーパークラスとサブクラス
- スーパークラス(superclass/スーパークラス):継承元・親クラス・基底クラス
- サブクラス(subclass/サブクラス):継承先・子クラス・派生クラス
class Animal: # スーパークラス
def __init__(self, name):
self.name = name
def speak(self):
return "鳴き声"
class Dog(Animal): # サブクラス
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
def speak(self):
return "ワン"
super()
super(スーパー)は、MRO(エム・アール・オー/Method Resolution Order:メソッド解決順序)に従って、次のクラスの処理を呼び出します。
dog = Dog("Pochi", "Shiba")
print(dog.name)
print(dog.speak())
オーバーライド
オーバーライド(override/オーバーライド)は、スーパークラスと同名のメソッドをサブクラスで定義し、処理を上書きすることです。
class Cat(Animal):
def speak(self):
return "ニャー"
継承を使うメリット
- 共通処理を1か所へまとめられる
- 重複コードを減らせる
- スーパークラス型として共通に扱える
- サブクラスごとの差分だけ実装できる
- ポリモーフィズムを利用できる
継承を使う判断
継承は「サブクラスはスーパークラスの一種である」という is-a(イズ・ア)関係のときに向いています。
-
Dog is an Animal:自然 -
Car is an Engine:不自然
部品として利用する has-a(ハズ・ア)関係なら、継承よりコンポジション(composition/コンポジション、委譲・組み合わせ)が適しています。
class Engine:
def start(self):
return "engine started"
class Car:
def __init__(self):
self.engine = Engine() # Car has an Engine
多重継承
多重継承は、1つのクラスが複数のクラスを継承することです。
class Flyable:
def fly(self):
return "飛ぶ"
class Swimmable:
def swim(self):
return "泳ぐ"
class Duck(Flyable, Swimmable):
pass
duck = Duck()
print(duck.fly())
print(duck.swim())
多重継承の注意
- 同名メソッドがある場合はMROで呼び出し順が決まる
-
super()は単純な「親クラス指定」ではなく、MRO上の次のクラスを呼ぶ - 菱形継承では処理順が分かりにくくなりやすい
- 小さな機能を追加するMixin(ミックスイン)として使うと整理しやすい
print(Duck.mro())
# メソッドを探す順番を確認できる
説明するときの一言:
継承は共通機能を引き継ぐ仕組み、オーバーライドは子クラスで処理を差し替える仕組み、多重継承は複数クラスの機能を引き継ぐ仕組みです。
12. コールスタック・スタックトレース
スタック
スタック(stack/スタック)は、後から入れたものを先に取り出すデータ構造です。
LIFO(ライフォ/Last In, First Out:後入れ先出し)と呼びます。
コールスタック
コールスタック(call stack/コールスタック)は、実行中の関数呼び出しを管理する仕組みです。
main() を呼ぶ
└─ calculate() を呼ぶ
└─ divide() を呼ぶ
- 関数を呼ぶと、実行情報であるフレームが積まれる
- 関数が終了すると、そのフレームが取り除かれる
- 現在実行中の最も深い関数がスタックの一番上にある
def divide(a, b):
return a / b
def calculate():
return divide(10, 0)
def main():
calculate()
main()
スタックトレース
スタックトレース(stack trace/スタックトレース)は、例外発生までにどの関数を通ったかを示す記録です。Pythonでは traceback(トレースバック)とも呼びます。
Traceback (most recent call last):
File "app.py", line 13, in <module>
main()
File "app.py", line 10, in main
calculate()
File "app.py", line 6, in calculate
return divide(10, 0)
File "app.py", line 2, in divide
return a / b
ZeroDivisionError: division by zero
スタックトレースの見方
-
一番下の例外名とメッセージを読む
ZeroDivisionError: division by zero -
そのすぐ上のファイル名・行番号・コードを見る
実際に例外が発生した場所に近い -
下から上へ呼び出し元をたどる
どの処理経由でその行へ来たか確認する -
自分が書いたファイルを優先して確認する
ライブラリ内部の行より、最初に渡した不正な値を探す - 例外の原因となった変数の値・型を確認する
Pythonの表示順は、上が古い呼び出し、下が例外発生に近い呼び出しです。そのため、基本は一番下から読みます。
ログへトレースバックを出す
import logging
try:
result = 10 / 0
except ZeroDivisionError:
logging.exception("計算処理に失敗しました")
logging.exception()(ロギング・エクセプション)は、except ブロック内で使うとスタックトレースも記録します。
説明するときの一言:
コールスタックは関数の呼び出し履歴、スタックトレースは例外発生時にその履歴を表示したものです。
13. 例外処理
一般的な例外
| 例外 | 読み方 | 主な原因 |
|---|---|---|
SyntaxError |
シンタックスエラー | 文法が不正 |
IndentationError |
インデンテーションエラー | インデントが不正 |
NameError |
ネームエラー | 未定義の名前を使用 |
UnboundLocalError |
アンバウンドローカルエラー | ローカル変数へ代入前に参照 |
TypeError |
タイプエラー | 型に合わない操作・引数 |
ValueError |
バリューエラー | 型は正しいが値が不正 |
AttributeError |
アトリビュートエラー | 存在しない属性・メソッド |
KeyError |
キーエラー | 辞書にキーがない |
IndexError |
インデックスエラー | リスト等の位置が範囲外 |
ZeroDivisionError |
ゼロディビジョンエラー | 0で除算 |
FileNotFoundError |
ファイルノットファウンドエラー | ファイルが存在しない |
PermissionError |
パーミッションエラー | 権限がない |
ModuleNotFoundError |
モジュールノットファウンドエラー | モジュールが見つからない |
AssertionError |
アサーションエラー |
assert の条件が偽 |
TimeoutError |
タイムアウトエラー | 処理が規定時間を超えた |
TypeError と ValueError の違い
len(100) # TypeError:この型にはlenを使えない
int("abc") # ValueError:str型は受け取れるが、内容を整数化できない
try / except
def calculate(text):
try:
number = int(text)
result = 100 / number
except ValueError as error:
print(f"整数へ変換できません: {error}")
except ZeroDivisionError:
print("0では割れません")
else:
print(f"計算結果: {result}")
finally:
print("処理終了")
| キーワード | 役割 |
|---|---|
try |
例外が発生する可能性のある処理 |
except |
指定した例外が発生した場合の処理 |
else |
例外が発生しなかった場合だけ実行 |
finally |
例外の有無にかかわらず最後に実行 |
raise
raise は、意図的に例外を発生させます。
def register_age(age):
if age < 0:
raise ValueError("年齢は0以上で指定してください")
return age
捕捉後に同じ例外を再送出する
import logging
try:
result = 100 / 0
except ZeroDivisionError:
logging.exception("計算に失敗しました")
raise
引数なしの raise は、現在処理中の例外をそのまま上位へ送ります。
例外を変換し、原因を残す
class OrderError(Exception):
pass
def load_order(order_id):
try:
return int(order_id)
except ValueError as error:
raise OrderError("注文IDが不正です") from error
raise ... from ... により、元の例外との因果関係をスタックトレースに残せます。
独自例外
class InsufficientStockError(Exception):
"""在庫不足を表す例外。"""
def purchase(stock, quantity):
if quantity > stock:
raise InsufficientStockError("在庫が不足しています")
finally と後処理
file = None
try:
file = open("sample.txt", encoding="utf-8")
print(file.read())
finally:
if file is not None:
file.close()
ファイルのようなリソースは、通常 with 文を使う方が安全です。
with open("sample.txt", encoding="utf-8") as file:
print(file.read())
例外処理の注意
-
except:だけで全例外をまとめて捕捉しない - 可能な限り具体的な例外型を捕捉する
-
tryの範囲を必要最小限にする - 例外を握りつぶさず、処理・記録・再送出のいずれかを行う
-
finally内でreturnしない。元の例外や戻り値を隠す可能性がある -
Exceptionは通常のアプリケーション例外の基底クラス -
KeyboardInterruptやSystemExitまで一括捕捉するBaseExceptionは通常捕捉しない - クリーンアップ目的なら、可能な場合は
with文を優先する
説明するときの一言:
例外処理は、異常発生時にプログラムをただ停止させるのではなく、記録・代替処理・後片付け・上位への通知を行う仕組みです。
14. まとめ
データ型
intは整数、floatは小数、strは文字列です。
listは変更できる順序付きの集まり、tupleは変更できない順序付きの集まりです。
dictはキーと値の対応、setは重複しない値の集合を扱います。
dateは日付、datetimeは日付と時刻を扱います。
リストと辞書の違い
リストは「何番目か」という位置で値を扱い、辞書は「名前やIDなどのキー」で値を扱います。
順番に並べたデータはリスト、項目名と値を対応づけたいデータは辞書が適しています。
# リスト:位置で取得
products = ["book", "pen"]
print(products[0])
# 辞書:キーで取得
product = {"name": "book", "price": 1200}
print(product["name"])
オブジェクト指向
クラスは設計図、インスタンスは設計図から作った実体です。
データをインスタンス変数、処理をメソッドとしてまとめます。
三大要素は、内部を守るカプセル化、共通機能を引き継ぐ継承、同じ呼び出しで異なる動きを実現するポリモーフィズムです。
__init__ と __main__
__init__はインスタンス作成時の初期化メソッドです。
__main__はそのPythonファイルが直接実行されたことを示す特別なモジュール名です。
スタックトレース
スタックトレースは、例外発生までに通った関数と行番号の履歴です。
一番下の例外名とメッセージを確認し、その直上の発生箇所から上へたどります。
例外処理
tryに失敗する可能性のある処理、exceptに例外発生時の処理を書きます。
elseは成功時、finallyは成功・失敗にかかわらず最後に実行されます。
raiseは、異常を検知した側から明示的に例外を通知するために使います。
最低限覚えたいコード
from datetime import datetime
def main():
users = [
{"name": "Cake", "score": 80},
{"name": "Cookie", "score": 95},
]
try:
high_scores = [user for user in users if user["score"] >= 90]
for user in high_scores:
print(f"{user['name']}: {user['score']}点")
print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
except KeyError as error:
print(f"必要なキーがありません: {error}")
if __name__ == "__main__":
main()