仮の宿 学習室

クラウド・AI・Python CLOUD / AI / PYTHON

例外とクラスと標準ライブラリ

講義 3 本・確認問題 30 問 | 本試験では「Python3基礎」(0問)の一部 | 最終更新 2026-09-24

この章で学ぶこと
目次
  1. 例外 tryとexceptと例外の階層
  2. クラス 継承とMROと特殊メソッド
  3. 標準ライブラリとイテレータ
  4. 確認問題(30問)
  5. 演習ツール

1. 例外 tryとexceptと例外の階層

try except else finally がどの順に走るのか、例外はどんな親子関係で並んでいるのか、raise と assert は何をするのか。8章は出題40問中4問(10%)の重い章です。

プログラムが止まる止まり方には2種類あります。1つは構文エラーで、書き方そのものが Python の文法に合っていないもの。これは実行される前に弾かれます。もう1つが例外で、書き方は正しいのに実行してみたら実行できなかったもの。0で割った、無い鍵で辞書を引いた、数字でない文字列を int() に渡した。例外処理はこの後者を扱う仕組みです。

基本の形は try と except です。try のブロックを上から実行し、途中で例外が起きたらそこで中断して、種類が合う except に飛びます。合う except が1つも無ければ、その例外は呼び出し元へ伝わっていき、最後まで誰も受け止めなければプログラムが止まります。except のうしろに as e と書くと、飛んできた例外オブジェクトそのものを受け取れます。e.args に raise へ渡された引数がタプルで入り、str(e) でメッセージが読めます。

ここに else と finally が加わります。else は try で例外が起きなかったときだけ実行されるブロックです。名前が紛らわしいのですが、if の else とは逆で「うまくいったとき」の側です。finally は例外が起きても起きなくても必ず実行されるブロックで、ファイルを閉じるような後片付けを置く場所です。実行順は、例外が無ければ try、else、finally。例外があって捕まえたなら try の途中まで、except、finally。この2本の道筋を頭に入れておけば、出力を並べる問題はほぼ解けます。

finally の性質でいちばん問われるのが return との関係です。try の中に return があっても、finally は return より前に実行されます。値を返す準備ができてから、いったん finally に寄って、それから返るのだと考えてください。そして finally の中にも return があると、そちらが戻り値を上書きしてしまいます。try で return したはずの値が消えるので、finally に return を書くのは避けるのが定石です。

例外にはクラスの親子関係があります。頂点は BaseException で、その直下に Exception があり、普段使う例外のほとんどは Exception の下にぶら下がっています。except Exception と書けば、その下の子孫はまとめて捕まえられます。逆にいうと、Exception の下にいない KeyboardInterrupt と SystemExit は except Exception では捕まりません。この2つは BaseException の直下にいて、利用者が Ctrl-C で止めたときやプログラムが自分で終了するときのものなので、うっかり握りつぶさないよう別枠にしてあるのです。

中間の親も覚える価値があります。IndexError と KeyError はどちらも LookupError の下です。添字でも鍵でも「引いたが見つからない」という同じ性質なので、まとめて except LookupError で受けられます。ZeroDivisionError は ArithmeticError の下、FileNotFoundError は OSError の下、ModuleNotFoundError は ImportError の下です。親クラスを書けば子も捕まるので、except を並べるときは必ず狭いもの(子)を先、広いもの(親)を後に書きます。順序を逆にすると、先に書いた親がすべて拾ってしまい、後ろの except は永遠に出番が来ません。複数をまとめたいときは except (ValueError, TypeError) のようにタプルで並べます。丸括弧を忘れるとエラーになります。

自分で例外を起こすのが raise です。raise ValueError('負の数は不可') のようにインスタンスを渡します。except の中で引数を付けずに raise とだけ書くと、いま処理中の例外をそのまま呼び出し元へ投げ直します。ログだけ残して判断は上に任せたい、というときの書き方です。独自の例外を作るときは class LoadError(Exception): pass のように Exception を継承したクラスを定義するだけでよく、中身が空でも例外として使えます。Exception を継承しておけば except Exception でも拾えるようになります。

assert は「ここでは必ずこうなっているはず」を書き残す文です。assert 条件, メッセージ と書き、条件が偽なら AssertionError が上がります。ただし python3 -O のように最適化モードで実行すると assert は丸ごと無効化され、1行も実行されません。したがって assert を入力値の検証に使ってはいけません。利用者が入れた値をはねるのは if と raise の仕事で、assert は開発時の自己点検に使うものだ、と役割を分けて覚えてください。

よく出る例外と、それが上がる場面と、直近の親
例外上がる場面直近の親
ZeroDivisionError0 で割ったArithmeticError
ValueError型は合うが値が不適切(int('abc'))Exception
TypeError型が合わない('a'+1、len(5))Exception
IndexError並びの範囲外の添字LookupError
KeyError辞書に無い鍵LookupError
NameError定義していない名前を使ったException
FileNotFoundError無いファイルを開いたOSError
ModuleNotFoundError無いモジュールを import したImportError
KeyboardInterrupt利用者が Ctrl-C で止めたBaseException
else と finally の通り道を確かめる。出力は 変換できました/後片付け/30/数字ではありません/後片付け/-1 の順
def read_age(s):    try:        n = int(s)    except ValueError:        print("数字ではありません")        return -1    else:        print("変換できました")        return n    finally:        print("後片付け") print(read_age("30"))print(read_age("x"))

用語

例外
文法としては正しいのに、実行してみると続行できなかったときに送出されるオブジェクト。構文エラーは実行前に弾かれるので別物。
else 節
try で例外が起きなかったときだけ実行される。if の else とは向きが逆で、成功した側に付く。
finally 節
例外の有無にかかわらず必ず実行される。try に return があっても finally が先に走り、finally に return があると戻り値を上書きする。
BaseException
例外階層の頂点。直下に Exception のほか KeyboardInterrupt と SystemExit がいる。この2つは except Exception では捕まらない。
LookupError
IndexError と KeyError の共通の親。添字でも鍵でも「引いたが見つからない」場面をまとめて受けられる。
ArithmeticError
ZeroDivisionError や OverflowError の親。except ArithmeticError と書けば 0 除算も捕まる。
except のタプル指定
except (ValueError, TypeError) as e のように丸括弧で並べると、どれか1つに一致したときに実行される。
引数なしの raise
except の中で raise とだけ書くと、いま処理中の例外をそのまま呼び出し元へ再送出する。
自作例外
Exception を継承したクラスを定義するだけで作れる。中身が pass だけでも例外として送出でき、except Exception でも拾える。
assert
条件が偽なら AssertionError を送出する文。python3 -O では無効化されるので、入力値の検証には使わない。

例題

例題:例題:except Exception と書いておけば、実行中に起きうる異常はすべて受け止められると考えてよいか。
答えと考え方 いいえ。Exception の下にぶら下がっている例外だけです。KeyboardInterrupt と SystemExit は BaseException の直下にいるので、except Exception では捕まりません。これは仕様上そうしてあるもので、利用者が Ctrl-C で止めようとしたのに握りつぶされて止まらない、といった事故を防いでいます。本当にすべてを受けたいときだけ except BaseException と書きますが、止められないプログラムになりがちなので普段は使いません。
例題:例題:except を2つ並べたのに、後ろの except が一度も実行されない。何を疑うか。
答えと考え方 並び順です。except は上から順に照合し、最初に一致したところで打ち切ります。先に親クラスを書いてしまうと、その子孫はすべて親のほうで拾われ、後ろに書いた子クラスの except には出番が来ません。ArithmeticError を先、ZeroDivisionError を後に書いた場合がまさにこれです。狭いものを先、広いものを後、という順に並べ替えてください。
例題:例題:入力欄に負の数が入っていないかを assert で確かめている。この設計の何が危ういか。
答えと考え方 本番を python3 -O で動かすと assert が丸ごと無効になり、検査が消えてしまうことです。assert は開発中の自己点検のための文で、実行時に必ず効く保証がありません。利用者の入力をはねるなら if で条件を見て raise ValueError(...) を投げる形にします。assert は「ここに来る時点で計算済みのはず」といった、内部の前提を書き残す用途に限るのが安全です。

出典・根拠:Python Software Foundation「Python チュートリアル 8. エラーと例外」Python 3.14 ドキュメント(2026年8月確認)

2. クラス 継承とMROと特殊メソッド

self とは何か、クラス変数とインスタンス変数はどこが違うのか、多重継承のときどの親が選ばれるのか。9章は2問ですが、クラス変数の共有と MRO は取りこぼしやすい論点です。

クラスは、データとそれを扱う手続きをひとまとめにした型の設計図です。class Dog: と書いて中にメソッドを並べ、Dog("Rex") と呼ぶとインスタンスが1つ作られます。作られる途中で自動的に呼ばれるのが __init__ で、ここでそのインスタンス固有のデータを self に持たせます。__init__ は「初期化するメソッド」であって、インスタンスそのものを作って返すメソッドではありません。

メソッドの第1引数 self は、呼び出したインスタンス自身が自動的に入る場所です。d.speak() と書くと Python が裏で Dog.speak(d) に読み替えています。ですから self という名前自体は決まりごとではなく単なる慣習で、第1引数が自分自身を受けるという位置だけが仕様です。逆に Dog.speak(d) と自分で書いても同じように動きます。

つまずきどころの筆頭がクラス変数とインスタンス変数の違いです。class の直下に書いた変数はクラス変数で、そのクラスから作られた全インスタンスが同じ1つを共有します。__init__ の中で self.名前 = 値 と書いたものはインスタンス変数で、インスタンスごとに別々に持ちます。Dog.kind = "wolf" とクラス側を書き換えると、すべてのインスタンスから見える値が変わります。一方 d.kind = "husky" とインスタンス側に代入すると、そのインスタンスの __dict__ に kind が新しく作られ、クラス変数の上に影を落とします。以後 d.kind はその影を返し、ほかのインスタンスとクラス変数は元のままです。

この違いが牙をむくのが、リストや辞書のようなミュータブルなオブジェクトをクラス変数にしたときです。class Basket: items = [] と書いて self.items.append(x) とすると、self.items は代入ではなく参照なので、たどり着く先はクラス変数の1つのリストです。結果として、どのインスタンスから足しても全員の items が同じ内容になります。インスタンスごとに別々の入れ物が欲しければ、__init__ の中で self.items = [] と代入して作ってください。self.count += 1 のように数値のクラス変数を増やそうとしたときも同じ理屈が働きますが、こちらは += が代入なので、クラス変数は 0 のまま、インスタンス側に 1 という影ができます。

継承は class Cat(Animal): のように親クラスを書きます。子で同じ名前のメソッドを定義すれば上書き(オーバーライド)になり、親の実装も呼びたいときは super() を使います。子の __init__ の中で super().__init__(name) と呼ぶのが定番で、親が用意していた初期化をやってから、子だけの属性を足すという流れになります。super() を書き忘れると親の __init__ が走らないので、親が用意するはずだった属性が存在しないインスタンスができあがります。

親を2つ以上書けるのが多重継承です。このとき、どの親のメソッドが使われるかを決める並びが MRO(メソッド解決順序)で、クラス.__mro__ で確認できます。並びは C3線形化という規則で作られ、単純な深さ優先ではありません。A を親に持つ B と C があり class D(B, C) とすると、MRO は D、B、C、A、object です。B から A へ潜ってしまわず、いったん C を見てから A に行く点が肝で、これは共通の親 A を子より先に置かないという規則によります。class E(C, B) と書けば E、C、B、A、object になり、先に書いたほうが優先されます。矛盾する順序を要求すると、そもそもクラス定義の時点で TypeError になります。B が A を継承しているのに class F(A, B) と書くと、A を B より先にしたいという指定と、親は子より後という規則がぶつかるためです。

属性を外から触られたくないときは名前の先頭にアンダースコアを付けます。_x のように1本だけ付けるのは「内部用のつもりです」という慣習の合図にすぎず、外から普通に読み書きできます。__x のように2本付けると名前修飾(ネームマングリング)が働き、実際の属性名が _クラス名__x に書き換えられます。そのため p.__x と書くと AttributeError になりますが、p._P__x と書けば読めます。本来の目的は、継承したときに親子で属性名がぶつかるのを防ぐことで、アクセス制限そのものではありません。Python に private キーワードはありません。

先頭と末尾にアンダースコアが2本ずつ付く名前は特殊メソッドで、組み込みの構文や関数から呼ばれます。print(v) や str(v) は __str__、repr(v) とリストや辞書の中に入れて表示したときは __repr__ が使われます。__str__ が無ければ __repr__ で代用されますが、逆はありません。len(v) は __len__、v + w は __add__、v == w は __eq__ です。ここで1つ落とし穴があり、__eq__ を定義したクラスは __hash__ が自動的に None にされます。等しさの定義を変えたのにハッシュ値が元のままだと集合や辞書が壊れるためで、その結果 set に入れようとすると unhashable type というエラーになります。ハッシュも使いたいなら __hash__ も自分で定義してください。

クラス変数とインスタンス変数の見え方
操作そのインスタンスほかのインスタンスクラス側
クラス変数に代入(Dog.kind = 'wolf')変わる変わる変わる
インスタンスに代入(d.kind = 'husky')変わる元のまま元のまま
ミュータブルなクラス変数を変更(self.items.append(x))変わる変わる変わる
__init__ で作ったリストを変更(self.items.append(x))変わる元のままそもそも持たない
n はインスタンスごと、total はクラス全体。出力は left:2 right:1 3。総数を数えたいときは Counter.total と明示して増やす
class Counter:    total = 0     def __init__(self, label):        self.label = label        self.n = 0     def tick(self):        self.n += 1        Counter.total += 1     def __str__(self):        return "{}:{}".format(self.label, self.n) a = Counter("left")b = Counter("right")a.tick()a.tick()b.tick()print(a, b, Counter.total)

用語

__init__
インスタンスが作られた直後に自動で呼ばれる初期化のメソッド。インスタンスを生成して返すものではない。
self
メソッドの第1引数に自動で渡される、呼び出したインスタンス自身。名前は慣習で、位置だけが仕様。
クラス変数
class の直下に書いた変数。全インスタンスで1つを共有する。クラス側を書き換えると全員に波及する。
インスタンス変数
self.名前 = 値 で作る、インスタンスごとに別々の変数。同名のクラス変数があれば、その上に影を落とす。
super()
MRO 上で次に来るクラスを参照する。子の __init__ から super().__init__(...) と呼んで親の初期化を行うのが定番。
MRO
メソッド解決順序。C3線形化で決まり、クラス.__mro__ で確認できる。class D(B, C) なら D、B、C、A、object。
名前修飾
__x のようにアンダースコア2本で始まる属性名が _クラス名__x に書き換えられる仕組み。継承時の名前衝突を防ぐためのもの。
__str__ と __repr__
前者は print() や str() が使う読みやすい表現、後者は repr() やコンテナの中で使われる表現。__str__ が無ければ __repr__ で代用される。
__eq__
== の振る舞いを決める特殊メソッド。定義すると __hash__ が None になり、そのままでは集合や辞書のキーに使えなくなる。
特殊メソッド
前後にアンダースコアが2本ずつ付く名前。__len__ は len()、__add__ は + など、組み込みの構文から呼ばれる。

例題

例題:例題:クラスの中に設定用の辞書を1つ置いておきたい。class 直下に書くか、__init__ の中で作るか、どう決めるか。
答えと考え方 全インスタンスで同じ1つを共有してよいなら class 直下(クラス変数)、インスタンスごとに別々に持たせたいなら __init__ の中で self に代入します。判断を誤ると、片方のインスタンスで設定を書き換えたつもりが全員に反映されてしまいます。共有したい定数のうち、書き換えないもの(文字列や数値)なら class 直下でもほぼ困りませんが、辞書やリストのように中身を書き換えるものは、共有してよいかを必ず先に決めてください。
例題:例題:class Sub(Base) を書いて Sub("名前") としたら、Base が用意するはずの属性が無いと言われた。何を忘れているか。
答えと考え方 子の __init__ の中で super().__init__("名前") を呼び忘れています。子が __init__ を定義した時点で親の __init__ は上書きされ、自動では走りません。親が self に持たせるはずだった属性が作られないまま、そのインスタンスが出来上がります。子で __init__ を定義するなら、原則として最初に super().__init__(...) を呼ぶ、と覚えておくと安全です。
例題:例題:自作クラスを集合に入れたら unhashable type だと言われた。心当たりは。
答えと考え方 そのクラスで __eq__ を定義したはずです。__eq__ を定義すると __hash__ が自動的に None にされ、ハッシュを必要とする集合や辞書のキーに使えなくなります。等しさの定義を変えたのにハッシュ値が古いままだと、等しい2つが別の場所に入ってしまうためです。集合に入れたいなら、等しいときに同じ値を返す __hash__ を自分で定義します。値を変えないクラスなら、属性をタプルにまとめて hash() に渡す書き方が簡単です。

出典・根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

3. 標準ライブラリとイテレータ

math random datetime os.path sys re json collections。そしてイテレータとジェネレータ、map filter reduce、any all、is と ==。10章4問と11章1問ぶんの守備範囲です。

Python には最初から大量のモジュールが同梱されていて、import するだけで使えます。試験で顔を出すのは決まった顔ぶれなので、それぞれ何をする道具かと、返ってくる値の型を押さえておけば足ります。とくに「int が返るのか float が返るのか」「リストが返るのかイテレータが返るのか」を取り違える問題がよく出ます。

math は数学の関数です。math.pi は円周率、math.sqrt(16) は 4.0 で、割り切れても float が返る点に注意します。math.floor は下方向への切り捨てなので math.floor(-1.5) は -2、math.ceil は上方向なので math.ceil(-1.5) は -1 です。0 方向に丸める int(-1.5) が -1 になるのと結果が食い違うので、負の数で必ず確かめてください。random は乱数で、random.random() は 0.0 以上 1.0 未満の float、random.randint(1, 10) は両端を含む整数、random.choice(並び) は要素を1つ選びます。random.seed(値) を先に呼ぶと同じ並びが再現できます。

datetime は日付と時刻です。datetime.date(2026, 8, 22) で日付を作り、strftime('%Y/%m/%d') で書式を指定した文字列にします。日付どうしの引き算は timedelta を返し、日付に timedelta(days=10) を足すと10日後の日付になります。os.path はパスの文字列を組み立てたり分解したりする道具で、os.path.join('a', 'b') は区切り文字を補って 'a/b'、os.path.basename('/x/y/z.txt') は 'z.txt'、os.path.dirname は '/x/y' です。os.path.splitext('z.txt') は ('z', '.txt') のように拡張子だけを、点を付けたまま切り離したタプルを返します。sys はインタプリタ自身の情報で、sys.argv がコマンドライン引数のリスト、sys.path がモジュールを探すディレクトリのリスト、sys.version_info がバージョンです。

re は正規表現です。いちばん問われるのが re.match と re.search の違いで、match は文字列の先頭からしか照合しません。re.match('b', 'abc') は一致せず None を返しますが、re.search('b', 'abc') は途中でも探すので一致します。どちらも見つかればマッチオブジェクトを返し、.group() で一致した文字列、.groups() で丸括弧のグループをタプルで取り出せます。re.findall はすべての一致を文字列のリストで返し、re.sub は置換した文字列、re.split は分割したリストを返します。パターンには r'\d+' のような raw 文字列を使うのが習慣です。

json は Python のオブジェクトと JSON 文字列の相互変換です。json.dumps がオブジェクトから文字列へ、json.loads が文字列からオブジェクトへ。往復すると型が変わることがあるのが要点で、タプルは JSON の配列になり、戻すとリストになります。タプルには戻りません。辞書のキーは文字列化されるので、{1: 'a'} は '{"1": "a"}' になります。集合は JSON に対応する型が無いので json.dumps({1, 2}) は TypeError です。日本語は既定で \\uXXXX にエスケープされ、そのまま出したいときは ensure_ascii=False を渡します。

collections は用途を絞った入れ物の詰め合わせです。Counter は要素を数える辞書で、Counter('abracadabra') のように渡すと各文字の個数が入り、most_common(2) で多い順に2件のタプルのリストが返ります。無いキーを引いても KeyError にならず 0 が返ります。defaultdict(list) は未知のキーを引いた瞬間に空リストを作るので、いきなり append できます。namedtuple('Pt', 'x y') は名前でも添字でも読めるタプルを作り、isinstance(p, tuple) は True です。つまりタプルの一種であって、値を書き換えることはできません。deque は両端に高速に出し入れできる並びで、appendleft と popleft が使えます。

イテレータは、next() を呼ぶたびに次の値を1つ返し、尽きると StopIteration を送出するオブジェクトです。for 文は裏でこれを回しています。ここで最大のつまずきどころは、map filter zip enumerate と、あとで述べるジェネレータが、いずれもリストではなくイテレータを返すことです。イテレータは一度きりで、list() で取り出すと中身が空になります。同じ map オブジェクトに2回 list() をかけると、2回目は空リストになります。使い回したいなら、最初に list() でリストに固めてください。

ジェネレータは yield を含む関数から作られるイテレータです。ふつうの関数と決定的に違うのは、呼んだ時点では本体が1行も実行されないことです。返ってくるのはジェネレータオブジェクトだけで、最初の next() でようやく先頭から動きだし、yield に当たるとそこで止まって値を返します。次の next() で止まった続きから再開し、関数が終わると StopIteration になります。すべてをメモリに載せずに済むので、巨大な並びや無限の並びを扱えます。丸括弧で書く内包表記 (i*i for i in range(3)) はジェネレータ式で、角括弧のリスト内包表記とは返る型が違います。

map(関数, 並び) は各要素に関数を適用したイテレータ、filter(関数, 並び) は関数が真を返した要素だけのイテレータです。filter の第1引数に None を渡すと、要素そのものの真偽で絞り込み、0 や空文字列や None といった偽の要素が落ちます。functools.reduce(関数, 並び) は左から2つずつ畳み込んで1つの値にします。any は1つでも真なら True、all は全部真なら True ですが、空の並びを渡したときが逆転します。all([]) は True、any([]) は False です。「反例が1つも無いから真」「例が1つも無いから偽」と読むと筋が通ります。

最後に is と == です。== は値が等しいかを尋ね、is は同じオブジェクトかを尋ねます。a = [1, 2] と b = [1, 2] は a == b が True でも a is b は False で、中身が同じだけの別のリストだからです。c = a と代入した場合だけ c is a が True になります。None は1つしか存在しない特別なオブジェクトなので、x is None と書くのが作法です。整数や文字列で is を試すと、処理系のキャッシュ次第で結果が変わることがあるため、値を比べたいときは常に == を使ってください。

紛らわしい戻り値の型と値
書いたもの返るもの取り違えやすい答え
math.sqrt(16)4.0(float)4(int)と思いがち
math.floor(-1.5)-2(下方向)-1(0方向)と思いがち
re.match('b', 'abc')None(先頭のみ照合)一致すると思いがち
json.loads('[1, 2]')[1, 2](リスト)タプルに戻ると思いがち
list(map(str, [1, 2])) を2回1回目のみ値、2回目は []毎回同じ値と思いがち
all([])TrueFalse と思いがち
[1, 2] is [1, 2]FalseTrue と思いがち
出力は 4 24 / data/log.csv / [('i', 4)] / [5, 3, 4] / ['apple', 'kiwi']。map と filter は list() で包まないと中身が見えない
import mathimport os.pathfrom collections import Counter print(math.ceil(3.2), math.factorial(4))print(os.path.join("data", "log.csv"))print(Counter("mississippi").most_common(1))words = ["apple", "fig", "kiwi"]print(list(map(len, words)))print(list(filter(lambda w: len(w) > 3, words)))

用語

math.sqrt
平方根を返す。割り切れても float なので math.sqrt(16) は 4.0。math.floor(-1.5) は -2、math.ceil(-1.5) は -1。
os.path.splitext
パスを本体と拡張子に分けたタプルを返す。'z.txt' なら ('z', '.txt') で、点は拡張子側に付く。
re.match と re.search
match は文字列の先頭からしか照合しない。search は途中でも探す。一致しなければどちらも None。
json.loads
JSON 文字列を Python のオブジェクトへ戻す。JSON の配列はリストになり、元がタプルでもタプルには戻らない。
Counter
要素の個数を数える辞書。most_common(n) で多い順に n 件のタプルのリストを返し、無いキーは 0 を返す。
namedtuple
名前でも添字でも読めるタプルを作るファクトリ。作られたインスタンスは isinstance(p, tuple) が True。
イテレータ
next() で次の値を返し、尽きると StopIteration を送出する。map filter zip enumerate はこれを返すので一度きり。
ジェネレータ
yield を含む関数から作られるイテレータ。呼んだだけでは本体は動かず、最初の next() で先頭から実行が始まる。
filter(None, 並び)
第1引数が None のとき、要素そのものの真偽で絞る。0 や空文字列や None が落ちる。
all([]) と any([])
空の並びでは all は True、any は False。反例が無いから真、例が無いから偽、と読む。
is と ==
is は同じオブジェクトか、== は値が等しいか。中身の同じ別リストは == が True、is は False。None は is で比べる。

例題

例題:例題:list(map(...)) で作った結果を変数に入れずに map のまま持ち回り、2か所で使ったら、後のほうが空になった。なぜか。
答えと考え方 map が返すのはリストではなくイテレータで、一度取り出すと尽きるからです。最初の for や list() で全部読み切ってしまい、2回目には何も残っていません。2か所で使うなら、受け取った直後に list() でリストに固めます。同じことが filter zip enumerate とジェネレータでも起きるので、「複数回まわすならリストにする」と決めておくと事故が減ります。
例題:例題:条件を満たす要素が1つも無い並びに対して all() を呼んだら True が返った。バグか。
答えと考え方 仕様どおりです。all は「偽の要素が1つも無い」ときに True を返すので、そもそも要素が無い空の並びでは True になります。逆に any は「真の要素が1つ以上ある」ときに True なので、空なら False です。空になりうる並びを all で判定するときは、len(並び) > 0 を先に確かめるか、and で組み合わせて意図を明示してください。
例題:例題:設定を辞書にして json.dumps で保存し、json.loads で読み戻したら、タプルだったはずの項目がリストになっていた。どう直すか。
答えと考え方 JSON にはタプルという型が無いので、これは往復での型の変化として避けられません。dumps の時点でタプルは配列になり、loads はそれをリストとして戻します。タプルが必要なら、読み戻したあとにアプリケーション側で tuple() に変換します。同じ理屈で、辞書のキーは文字列化され、集合は json.dumps の時点で TypeError になります。JSON で表せる型に寄せてから保存するのが基本です。

出典・根拠:Python Software Foundation「Python チュートリアル 10. Brief tour of the standard library」Python 3.14 ドキュメント(2026年8月確認)

確認問題(30問)

四肢択一。「正解と解説」を開くと、正解の理由と他の選択肢が違う理由を確認できます。

問1|try文の順序

次のコードを実行したとき、出力される行を上から順に並べたものはどれか。

def calc(a, b):    try:        print("try")        r = a / b    except ZeroDivisionError:        print("except")    else:        print("else")    finally:        print("finally") calc(9, 3)
  1. try と except と finally
  2. try と else と except
  3. try と else と finally
  4. try と except と else
正解と解説
正解:C. try と else と finally

9 / 3 は例外を出さないので except には入らない。例外が起きなかったときだけ実行されるのが else 節なので、try のあとに else が実行される。finally 節は例外の有無にかかわらず必ず実行されるので最後に走る。したがって try、else、finally の3行になる。except が出てくる選択肢は例外が起きたと誤解した場合の並びで、この呼び出しでは ZeroDivisionError は発生しない。finally が抜けている選択肢は、finally を「例外が起きたときの後始末」と取り違えた場合の並びである。

根拠:Python Software Foundation「Python チュートリアル 8. エラーと例外」Python 3.14 ドキュメント(2026年8月確認)

問2|else節

try 文の else 節が実行される条件として正しいものはどれか。

  1. try 節で例外が発生しなかったときだけ実行される
  2. try 節で例外が発生したときだけ実行される
  3. 例外の発生にかかわらず、常に最後に実行される
  4. どの except 節にも一致しなかったときに実行される
正解と解説
正解:A. try 節で例外が発生しなかったときだけ実行される

try 文の else 節は、try 節が最後まで例外を出さずに終わったときにだけ実行される。if 文の else が「条件が偽のとき」であるのに対し、try 文の else は「うまくいったとき」の側に付くので向きが逆だと覚えるとよい。例外が発生したときに実行されるのは except 節である。例外の有無にかかわらず必ず実行されるのは finally 節のほう。どの except にも一致しなかった場合は else に落ちるのではなく、その例外は呼び出し元へ伝わっていく。

根拠:Python Software Foundation「Python チュートリアル 8. エラーと例外」Python 3.14 ドキュメント(2026年8月確認)

問3|finally優先

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

def f():    try:        return "T"    finally:        print("F") def g():    try:        return "T"    finally:        return "N" print(f(), g())
  1. T N と F の2行が出力される
  2. F と T T の2行が出力される
  3. T T と F の2行が出力される
  4. F と T N の2行が出力される
正解と解説
正解:D. F と T N の2行が出力される

f() は return する値を用意したあと、実際に返る前に finally 節を実行する。そのため F が先に表示され、戻り値は T のままになる。g() は finally 節の中に return があり、これが try 節の return を上書きするので戻り値は N になる。print は f() と g() を評価してから1行にまとめて表示するので、F の行が先、T N の行が後という順になる。T T になる選択肢は finally の return が無視されると考えた場合、F が後になる選択肢は finally が return のあとに走ると考えた場合の答えである。

根拠:Python Software Foundation「Python チュートリアル 8. エラーと例外」Python 3.14 ドキュメント(2026年8月確認)

問4|捕捉できない例外

except Exception と書いた except 節では捕捉できない例外はどれか。

  1. ZeroDivisionError
  2. KeyboardInterrupt
  3. FileNotFoundError
  4. ModuleNotFoundError
正解と解説
正解:B. KeyboardInterrupt

KeyboardInterrupt は BaseException の直下にあり、Exception を継承していない。issubclass(KeyboardInterrupt, Exception) は False になる。利用者が Ctrl-C で止めようとしたときのものなので、広めに書いた except Exception にうっかり握りつぶされないよう、階層を分けてある。SystemExit も同じ位置にいる。残りの3つはいずれも Exception の子孫で、ZeroDivisionError は ArithmeticError の下、FileNotFoundError は OSError の下、ModuleNotFoundError は ImportError の下にあるため、except Exception で捕捉できる。

根拠:Python Software Foundation「Python 標準ライブラリ 組み込み例外」Python 3.14 ドキュメント(2026年8月確認)

問5|例外の親

IndexError と KeyError に共通する直近の親クラスはどれか。

  1. ArithmeticError
  2. AttributeError
  3. ReferenceError
  4. LookupError
正解と解説
正解:D. LookupError

IndexError も KeyError も、添字や鍵で引いたが見つからなかったという同じ性質を持つため、LookupError という共通の親の下に置かれている。except LookupError と書けば、リストの範囲外アクセスと辞書の存在しない鍵の両方をまとめて受けられる。ArithmeticError は ZeroDivisionError などの親で、計算そのものが成立しない場面のもの。AttributeError は属性が見つからないとき、ReferenceError は弱参照の参照先が消えているときの例外で、どちらも Exception の直下にあり LookupError とは別系統である。

根拠:Python Software Foundation「Python 標準ライブラリ 組み込み例外」Python 3.14 ドキュメント(2026年8月確認)

問6|exceptの順

次のコードを実行したときの出力として正しいものはどれか。

try:    x = 8 / 0except ArithmeticError:    print("A")except ZeroDivisionError:    print("Z")
  1. A だけが出力される
  2. Z だけが出力される
  3. A と Z が出力される
  4. 何も出力されず停止する
正解と解説
正解:A. A だけが出力される

8 / 0 は ZeroDivisionError を送出するが、ZeroDivisionError は ArithmeticError の子クラスである。except 節は上から順に照合し、最初に一致したところで打ち切るので、先に書いた except ArithmeticError が拾ってしまい A だけが出力される。後ろの except ZeroDivisionError には出番が来ない。一致した except は1つしか実行されないので A と Z の両方が出ることはない。狭いもの(子クラス)を先、広いもの(親クラス)を後に並べるのが原則で、この順序を逆にしたのが本問のコードである。

根拠:Python Software Foundation「Python チュートリアル 8. エラーと例外」Python 3.14 ドキュメント(2026年8月確認)

問7|複数の例外

次のコードを実行したときに表示される1行はどれか。

def conv(s):    try:        return int(s) * 2    except (ValueError, TypeError) as e:        return type(e).__name__ print(conv("21"), conv("abc"), conv(None))
  1. 42 TypeError ValueError
  2. 42 ValueError ValueError
  3. 42 ValueError TypeError
  4. 42 TypeError TypeError
正解と解説
正解:C. 42 ValueError TypeError

except のうしろに丸括弧でくくったタプルを書くと、そのどれかに一致したときに実行される。conv("21") は int("21") が 21 になるので 42 を返す。conv("abc") は文字列としては渡せるが数値として解釈できないので ValueError になる。conv(None) は int() に渡せる型ではないので TypeError になる。型は正しいが値が不適切なら ValueError、そもそも型が合わなければ TypeError、という切り分けがそのまま答えの並びになる。

根拠:Python Software Foundation「Python チュートリアル 8. エラーと例外」Python 3.14 ドキュメント(2026年8月確認)

問8|再送出

自作例外と引数なしの raise を使った次のコードの出力はどれか。

class LoadError(Exception):    pass def load():    try:        raise LoadError("bad")    except LoadError:        print("inner")        raise try:    load()except Exception as e:    print("outer", type(e).__name__)
  1. inner だけで outer は出力されない
  2. inner と outer LoadError の2行
  3. inner のあと LoadError で停止する
  4. inner と outer Exception の2行
正解と解説
正解:B. inner と outer LoadError の2行

except の中で引数を付けずに raise とだけ書くと、いま処理中の例外をそのまま呼び出し元へ再送出する。したがって inner を表示したあと LoadError が load() の外へ伝わり、外側の except Exception が受け取る。LoadError は Exception を継承しているので except Exception で捕捉でき、停止はしない。type(e).__name__ は実際に送出された例外クラスの名前を返すので、捕まえた側の型名 Exception ではなく LoadError が表示される。inner だけになるのは、再送出せずその場で握りつぶしたときの出力である。

根拠:Python Software Foundation「Python チュートリアル 8. エラーと例外」Python 3.14 ドキュメント(2026年8月確認)

問9|未捕捉の例外

次のコードを実行すると、どのような結果になるか。

def get(seq, key):    try:        return seq[key]    except IndexError:        return "not found" print(get([1, 2, 3], 1))print(get({"a": 1}, "z"))
  1. 2 と None の2行が出力される
  2. 2 と KeyError の2行が出力される
  3. 2 と not found の2行が出力される
  4. 2 のあと KeyError で停止する
正解と解説
正解:D. 2 のあと KeyError で停止する

1つ目の呼び出しはリストの添字 1 なので 2 が返る。2つ目は辞書に無い鍵を引くので KeyError が送出されるが、except に書いてあるのは IndexError だけである。IndexError と KeyError はどちらも LookupError の子だが互いに親子ではないので、IndexError の except では KeyError を捕まえられない。捕捉されなかった例外は呼び出し元へ伝わり、受け止める者がいないのでプログラムが停止する。両方を受けたいなら except LookupError と書くか、タプルで両方を並べる。

根拠:Python Software Foundation「Python 標準ライブラリ 組み込み例外」Python 3.14 ドキュメント(2026年8月確認)

問10|assert

assert 文の説明として正しいものはどれか。

  1. 条件が偽なら AssertionError を送出し、python3 -O では無効化される
  2. 条件が真なら AssertionError を送出し、python3 -O では無効化される
  3. 条件が偽なら AssertionError を送出し、python3 -O でも必ず実行される
  4. 条件が偽なら ValueError を送出し、python3 -O でも必ず実行される
正解と解説
正解:A. 条件が偽なら AssertionError を送出し、python3 -O では無効化される

assert 条件, メッセージ は、条件が偽のときに AssertionError を送出する。条件が真のときは何も起こらない。重要なのは、python3 -O のように最適化モードで起動すると assert 文が丸ごと取り除かれ、1行も実行されないことである。したがって利用者の入力を検査する目的で assert を使ってはならず、その用途では if で条件を見て raise ValueError(...) を投げる。assert は開発中に内部の前提を書き残す道具だと役割を分けて覚えるとよい。

根拠:Python Software Foundation「Python チュートリアル 8. エラーと例外」Python 3.14 ドキュメント(2026年8月確認)

問11|self

メソッドの第1引数 self についての説明として正しいものはどれか。

  1. クラスそのものが自動的に渡される、予約された名前である
  2. 呼び出したインスタンス自身が自動的に渡される引数である
  3. インスタンスを生成して呼び出し元へ返すための引数である
  4. 親クラスの属性を参照するために予約された名前である
正解と解説
正解:B. 呼び出したインスタンス自身が自動的に渡される引数である

d.speak() と書くと Python は Dog.speak(d) に読み替えて呼び出す。このとき第1引数の位置に入るのが、呼び出したインスタンス自身である。self という綴りは慣習にすぎず、言語が予約している名前ではない。第1引数が自分自身を受けるという位置だけが仕様なので、Dog.speak(d) と自分で書いても同じように動く。インスタンスを作って返すのは __new__ とクラス呼び出しの仕組みの役目で、__init__ はすでに作られたインスタンスを初期化するだけである。親クラスの参照には super() を使う。

根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

問12|クラス変数

クラス変数を書き換えた次のコードの出力はどれか。

class Dog:    kind = "canine"     def __init__(self, name):        self.name = name a = Dog("Rex")b = Dog("Mia")Dog.kind = "wolf"print(a.kind, b.kind)
  1. canine canine
  2. wolf canine
  3. canine wolf
  4. wolf wolf
正解と解説
正解:D. wolf wolf

kind は class の直下に書かれたクラス変数で、そのクラスから作られた全インスタンスが同じ1つを共有する。a も b も自分の __dict__ に kind を持っていないため、属性を読むときはクラス側までさかのぼって同じ値を見る。Dog.kind への代入はその共有された1つを書き換えるので、すでに作られていた a と b の両方から wolf が見える。インスタンス生成のときに値がコピーされるわけではないので、canine が残る選択肢にはならない。

根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

問13|属性の影

インスタンス側に代入した次のコードの出力はどれか。

class Dog:    kind = "canine"     def __init__(self, name):        self.name = name a = Dog("Rex")b = Dog("Mia")a.kind = "husky"print(a.kind, b.kind, Dog.kind)print(sorted(a.__dict__))
  1. husky canine canine と ['kind', 'name']
  2. husky husky husky と ['kind', 'name']
  3. husky canine canine と ['name']
  4. husky husky husky と ['name']
正解と解説
正解:A. husky canine canine と ['kind', 'name']

a.kind への代入はクラス変数を書き換えず、a のインスタンス辞書に kind という新しい項目を作る。以後 a.kind を読むとこの新しい項目が先に見つかり、クラス変数に影を落とす形になる。b と Dog.kind は元の canine のままである。したがって a.__dict__ には __init__ で入れた name に加えて kind も並び、sorted すると ['kind', 'name'] になる。全部 husky になる選択肢はインスタンスへの代入がクラス変数を書き換えると誤解した場合、['name'] だけになる選択肢は影ができないと考えた場合の答えである。

根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

問14|共有される

リストをクラス変数にした次のコードの出力はどれか。

class Basket:    items = []     def add(self, x):        self.items.append(x) p = Basket()q = Basket()p.add(1)q.add(2)print(p.items, q.items)
  1. p.items は [1]、q.items は [2]
  2. p.items は [1]、q.items は [1, 2]
  3. p.items は [1, 2]、q.items は [1, 2]
  4. p.items は [1, 2]、q.items は [2]
正解と解説
正解:C. p.items は [1, 2]、q.items は [1, 2]

self.items.append(x) は self.items への代入ではなく、self.items でたどり着いたオブジェクトを呼び出しているだけである。p も q も自分の items を持たないので、たどり着く先はクラス変数の同じ1つのリストになる。結果として p から足した 1 も q から足した 2 も同じリストに入り、どちらから見ても [1, 2] になる。インスタンスごとに別々の入れ物が欲しいなら、__init__ の中で self.items = [] と代入して作る。そうすれば [1] と [2] に分かれる。

根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

問15|super()

継承と super() を使った次のコードの出力はどれか。

class Animal:    def __init__(self, name):        self.name = name    def cry(self):        return self.name + " ?" class Cat(Animal):    def __init__(self, name, color):        super().__init__(name)        self.color = color    def cry(self):        return self.name + " meow" c = Cat("Tama", "black")print(c.cry(), c.color, isinstance(c, Animal))
  1. Tama meow None True
  2. Tama meow black True
  3. Tama ? black True
  4. Tama meow black False
正解と解説
正解:B. Tama meow black True

Cat の __init__ は super().__init__(name) を呼んでいるので、親の Animal が self.name を設定してくれる。そのあと self.color に black を入れるため、両方の属性がそろう。cry は子で定義し直しているので親の実装は上書きされ、meow のほうが呼ばれる。isinstance(c, Animal) は、Cat が Animal を継承している以上 True になる。super() を書き忘れると name が設定されず AttributeError になるので、None になる選択肢のような静かな失敗にはならない。

根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

問16|MRO

多重継承した次のコードの出力はどれか。

class A:    def who(self):        return "A" class B(A):    def who(self):        return "B" class C(A):    def who(self):        return "C" class D(B, C):    pass print(D().who())print([k.__name__ for k in D.__mro__])
  1. C と ['D', 'C', 'B', 'A', 'object']
  2. B と ['D', 'B', 'A', 'C', 'object']
  3. A と ['D', 'B', 'C', 'A', 'object']
  4. B と ['D', 'B', 'C', 'A', 'object']
正解と解説
正解:D. B と ['D', 'B', 'C', 'A', 'object']

メソッド解決順序は C3線形化という規則で決まり、単純な深さ優先ではない。共通の親 A は、A を継承しているすべての子より後ろに置かれるため、D、B、C、A、object という並びになる。B に潜ったらそのまま A へ行く深さ優先だと D、B、A、C、object になるが、そうはならない点が要注意である。who() は MRO の先頭から探して最初に見つかったものが使われるので B が返る。class E(C, B) と書けば E、C、B、A、object になり、先に書いたほうが優先される。

根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

問17|MROの矛盾

class B(A) が定義済みのとき、class F(A, B): pass と書くと何が起こるか。

  1. 定義はでき、F().who() は A のものが呼ばれる
  2. 定義はでき、__mro__ は F、A、B、object になる
  3. クラス定義の時点で TypeError になる
  4. 定義はでき、F().who() は B のものが呼ばれる
正解と解説
正解:C. クラス定義の時点で TypeError になる

C3線形化には、基底クラスを並べた順序を守ることと、親は子より後ろに置くことという2つの決まりがある。F(A, B) は A を B より先に置けという指定だが、B は A の子なので親 A は子 B より後になければならない。この2つは同時に満たせないため、一貫した MRO を作れないとして、クラス定義を評価した時点で TypeError になる。実行してみるまで分からないのではなく、class 文を通過した瞬間に失敗する。正しくは class F(B, A) と、子を先に書く。

根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

問18|名前修飾

アンダースコアで始まる属性を持つ次のコードの出力はどれか。

class P:    def __init__(self):        self._one = 1        self.__two = 2 p = P()print(p._one, p._P__two)print(sorted(p.__dict__))
  1. 1 2 と ['_P__two', '_one']
  2. 1 2 と ['__two', '_one']
  3. 1 2 と ['_one', '_two']
  4. 1 2 と ['_P__one', '_P__two']
正解と解説
正解:A. 1 2 と ['_P__two', '_one']

アンダースコア1本で始まる _one は慣習として内部用を示すだけで、名前は変わらず外から普通に読める。アンダースコア2本で始まる __two には名前修飾が働き、実際の属性名が _P__two すなわち _クラス名__名前 に書き換えられる。そのため p.__two と書くと AttributeError になるが、p._P__two と書けば読める。__dict__ に並ぶのも修飾後の名前なので、sorted すると ['_P__two', '_one'] になる。修飾されるのは2本で始まるものだけで、_one は対象外である。

根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

問19|特殊メソッド

特殊メソッドを定義した次のコードの出力はどれか。

class Vec:    def __init__(self, x, y):        self.x = x        self.y = y    def __str__(self):        return "V({}, {})".format(self.x, self.y)    def __repr__(self):        return "Vec(x={}, y={})".format(self.x, self.y)    def __len__(self):        return 2    def __add__(self, o):        return Vec(self.x + o.x, self.y + o.y) v = Vec(1, 2)print(v)print([v])print(len(v), v + Vec(3, 4))
  1. V(1, 2) と [V(1, 2)] と 2 V(4, 6)
  2. V(1, 2) と [Vec(x=1, y=2)] と 2 V(4, 6)
  3. Vec(x=1, y=2) と [Vec(x=1, y=2)] と 2 V(4, 6)
  4. V(1, 2) と [Vec(x=1, y=2)] と 2 Vec(x=4, y=6)
正解と解説
正解:B. V(1, 2) と [Vec(x=1, y=2)] と 2 V(4, 6)

print(v) と str(v) は __str__ を使うので V(1, 2) になる。一方、リストや辞書などコンテナの中に入れて表示すると、要素それぞれについて __repr__ が使われるので [Vec(x=1, y=2)] になる。この使い分けが本問の要点である。len(v) は __len__ が返す 2、v + Vec(3, 4) は __add__ が返す新しい Vec で、それを print に渡すとまた __str__ が使われるので V(4, 6) と表示される。__str__ が定義されていないクラスでは __repr__ が代用されるが、逆に __repr__ の代わりに __str__ が使われることはない。

根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

問20|__eq__

__eq__ だけを定義した次のコードの出力はどれか。

class Point:    def __init__(self, x):        self.x = x    def __eq__(self, other):        return self.x == other.x p = Point(1)q = Point(1)print(p == q, p is q)print(Point.__hash__ is None)try:    print(len({p, q}))except TypeError:    print("TypeError")
  1. True False と False と 1
  2. True True と True と TypeError
  3. True False と True と TypeError
  4. True False と False と 2
正解と解説
正解:C. True False と True と TypeError

__eq__ を定義したので p == q は属性 x を比べて True になるが、p と q は別々に作られたオブジェクトなので p is q は False のままである。ここで重要なのは、__eq__ を定義したクラスは __hash__ が自動的に None に設定されることで、Point.__hash__ is None は True になる。ハッシュを持たないオブジェクトは集合や辞書のキーに使えないため、{p, q} を作ろうとすると TypeError になる。集合にも入れたいなら、等しいときに同じ値を返す __hash__ を自分で定義する必要がある。

根拠:Python Software Foundation「Python チュートリアル 9. クラス」Python 3.14 ドキュメント(2026年8月確認)

問21|math

math モジュールを使った次のコードの出力はどれか。

import math print(math.sqrt(16))print(math.floor(-1.5), math.ceil(-1.5))
  1. 4 と -2 -1
  2. 4.0 と -1 -2
  3. 4 と -1 -1
  4. 4.0 と -2 -1
正解と解説
正解:D. 4.0 と -2 -1

math.sqrt は割り切れる場合でも float を返すので、16 の平方根は 4 ではなく 4.0 と表示される。math.floor は数直線の下方向へ切り捨てるので -1.5 は -2 に、math.ceil は上方向なので -1.5 は -1 になる。負の数では、0 方向へ切り捨てる int(-1.5) が -1 になるのと floor の結果が食い違う点に注意する。floor と ceil を取り違えると -1 -2 の並びになり、sqrt の戻り値の型を int と思い込むと 4 になる。

根拠:Python Software Foundation「Python チュートリアル 10. Brief tour of the standard library」Python 3.14 ドキュメント(2026年8月確認)

問22|os.path

os.path.splitext('/tmp/z.txt') と os.path.basename('/tmp/z.txt') が返す値の組合せはどれか。

  1. ('/tmp', 'z.txt') と '/tmp'
  2. ('/tmp/z', '.txt') と 'z.txt'
  3. ('/tmp/z', 'txt') と 'z.txt'
  4. ('/tmp/z.txt', '') と 'z.txt'
正解と解説
正解:B. ('/tmp/z', '.txt') と 'z.txt'

os.path.splitext は拡張子だけを切り離し、点を拡張子側に付けたまま2要素のタプルを返す。したがって ('/tmp/z', '.txt') になる。点が落ちて 'txt' になることはない。os.path.basename はパスの末尾の名前を返すので 'z.txt' である。ディレクトリ側の '/tmp' を返すのは os.path.dirname のほうで、両方をまとめたタプルが欲しいときは os.path.split を使う。splitext はディレクトリの区切りではなく拡張子で切る、と役割を区別して覚えるとよい。

根拠:Python Software Foundation「Python チュートリアル 10. Brief tour of the standard library」Python 3.14 ドキュメント(2026年8月確認)

問23|reの照合

re モジュールを使った次のコードの出力はどれか。

import re print(re.match("b", "abc"))print(re.search("b", "abc").group())print(re.findall(r"\d+", "a1b22c333"))
  1. None と b と ['1', '22', '333']
  2. b と b と ['1', '22', '333']
  3. None と b と ['a1', 'b22', 'c333']
  4. b と None と ['1', '22', '333']
正解と解説
正解:A. None と b と ['1', '22', '333']

re.match は文字列の先頭からしか照合しないので、'abc' の先頭は 'a' であり 'b' には一致せず None を返す。re.search は途中でも探すので 'b' に一致し、.group() で一致した文字列 b が取り出せる。この違いが re でいちばん問われる。re.findall はパターンに一致した部分だけをすべて集めたリストを返し、\d+ は連続する数字なので ['1', '22', '333'] になる。区切りの文字まで含まれることはない。一致が無ければ空リストを返す。

根拠:Python Software Foundation「Python チュートリアル 10. Brief tour of the standard library」Python 3.14 ドキュメント(2026年8月確認)

問24|datetime

datetime を使った次のコードの出力はどれか。

import datetime d = datetime.date(2026, 8, 22)print(d)print(d.strftime("%Y/%m/%d"))print(d + datetime.timedelta(days=10))
  1. 2026-08-22 と 2026/08/22 と 2026-08-32
  2. 2026/08/22 と 2026/08/22 と 2026/09/01
  3. 2026-08-22 と 2026/08/22 と 2026-09-01
  4. 2026-08-22 と 2026/08/22 と 10 days, 0:00:00
正解と解説
正解:C. 2026-08-22 と 2026/08/22 と 2026-09-01

date オブジェクトをそのまま print すると、ISO 形式のハイフン区切りで 2026-08-22 と表示される。書式を変えたいときに使うのが strftime で、'%Y/%m/%d' を渡すとスラッシュ区切りの文字列 2026/08/22 が返る。date に timedelta(days=10) を足すと、返るのは timedelta ではなく10日後を指す新しい date なので、print すると 2026-09-01 と表示される。月をまたぐ計算は datetime 側が面倒を見てくれるので、日の数字に10を足しただけの 2026-08-32 のような存在しない日付にはならない。print(d) が strftime と同じ書式になると考えるとスラッシュ区切りが並ぶが、既定の表示はハイフン区切りである。日付どうしを引き算した場合は date ではなく timedelta が返り、その表示が 10 days, 0:00:00 のような形になる。

根拠:Python Software Foundation「Python チュートリアル 10. Brief tour of the standard library」Python 3.14 ドキュメント(2026年8月確認)

問25|Counter

collections.Counter を使った次のコードの出力はどれか。

from collections import Counter c = Counter("abracadabra")print(c.most_common(2))print(c["a"], c["z"])
  1. [('a', 5), ('b', 2), ('r', 2)] と 5 0
  2. [('a', 5), ('b', 2)] と 5 0
  3. [('a', 5), ('b', 2)] と 5 と KeyError
  4. [('a', 5), ('r', 2)] と 5 0
正解と解説
正解:B. [('a', 5), ('b', 2)] と 5 0

'abracadabra' には a が5個、b と r が2個ずつ、c と d が1個ずつ含まれる。most_common(2) は多い順に2件だけを、要素と個数のタプルのリストで返すので [('a', 5), ('b', 2)] になる。個数が同じ b と r は先に現れたほうが前に並ぶため b が採用される。Counter は辞書の一種だが、含まれない要素を引いても KeyError にはならず 0 を返す点が普通の辞書と違う。数え上げてから存在確認をしなくて済むようにするための設計である。

根拠:Python Software Foundation「Python チュートリアル 10. Brief tour of the standard library」Python 3.14 ドキュメント(2026年8月確認)

問26|namedtuple

namedtuple で作った型を使った次のコードの出力はどれか。

from collections import namedtuple Pt = namedtuple("Pt", "x y")p = Pt(1, 2)print(p)print(p.x, p[0], isinstance(p, tuple))
  1. (1, 2) と 1 1 True
  2. Pt(1, 2) と 1 1 False
  3. Pt(x=1, y=2) と 1 1 False
  4. Pt(x=1, y=2) と 1 1 True
正解と解説
正解:D. Pt(x=1, y=2) と 1 1 True

namedtuple が作る型は、表示すると型名とフィールド名が付いた Pt(x=1, y=2) という形になる。値は名前でも添字でも読めるので p.x と p[0] はどちらも 1 である。そして namedtuple はタプルの派生型なので isinstance(p, tuple) は True になる。つまりタプルの一種であり、要素を後から書き換えることはできない。書き換えたい値を持たせたいなら、値を差し替えた新しいインスタンスを作る _replace を使うか、通常のクラスを定義する。

根拠:Python Software Foundation「Python チュートリアル 10. Brief tour of the standard library」Python 3.14 ドキュメント(2026年8月確認)

問27|使い切り

同じ map オブジェクトを2回 list() に渡した次のコードの出力はどれか。

m = map(str, [1, 2, 3])print(list(m))print(list(m))
  1. 1行目は ['1', '2', '3']、2行目は []
  2. 1行目も2行目も ['1', '2', '3']
  3. 1行目は [1, 2, 3]、2行目は []
  4. 1行目は ['1', '2', '3']、2行目は None
正解と解説
正解:A. 1行目は ['1', '2', '3']、2行目は []

map が返すのはリストではなくイテレータで、next() のたびに次の値を1つ渡し、尽きたらそれきりである。1回目の list() で3つとも取り出してしまうため、2回目の list() は何も残っていない空リストになる。エラーにも None にもならず、静かに空になるので気づきにくい。map(str, ...) は各要素を文字列にするので、1回目の中身は数値ではなく ['1', '2', '3'] である。同じことが filter zip enumerate とジェネレータでも起こるため、複数回まわすなら受け取った直後に list() で固める。

根拠:Python Software Foundation「Python チュートリアル 10. Brief tour of the standard library」Python 3.14 ドキュメント(2026年8月確認)

問28|filterとall

filter と all と any を使った次のコードの出力はどれか。

print(list(filter(None, [0, 1, "", 2, None, "a"])))print(all([]), any([]))
  1. [1, 2, 'a'] と False True
  2. [0, '', None] と True False
  3. [1, 2, 'a'] と True False
  4. [1, 2, 'a'] と False False
正解と解説
正解:C. [1, 2, 'a'] と True False

filter の第1引数に None を渡すと、要素そのものの真偽で絞り込む。0 と空文字列と None は偽と評価されるので落ち、残るのは [1, 2, 'a'] である。落ちたほうが残るわけではない。all は偽の要素が1つも無ければ True を返す仕様なので、要素が1つも無い空のリストでは True になる。any は真の要素が1つ以上あれば True なので、空なら False である。空の並びを渡したときにこの2つが逆の答えを返す点が問われやすい。

根拠:Python Software Foundation「Python チュートリアル 10. Brief tour of the standard library」Python 3.14 ドキュメント(2026年8月確認)

問29|ジェネレータ

yield を含む関数を呼んだ次のコードで、出力される行の順序はどれか。

def gen():    print("start")    yield 1    print("mid")    yield 2 g = gen()print("created")print(next(g))print(next(g))
  1. start created 1 mid 2 の順
  2. created start 1 mid 2 の順
  3. start mid created 1 2 の順
  4. created start mid 1 2 の順
正解と解説
正解:B. created start 1 mid 2 の順

yield を含む関数を呼んでも、本体は1行も実行されない。返ってくるのはジェネレータオブジェクトだけなので、先に created が表示される。最初の next(g) でようやく先頭から動きだし、start を表示してから yield 1 で止まり 1 を返す。次の next(g) は止まった続きから再開して mid を表示し、yield 2 で止まり 2 を返す。この遅延実行が普通の関数との決定的な違いで、さらに next(g) を呼ぶと関数が終わって StopIteration になる。

根拠:Python Software Foundation「Python チュートリアル 9. クラス(イテレータ・ジェネレータ)」Python 3.14 ドキュメント(2026年8月確認)

問30|isと==

is 演算子と == 演算子を並べた次のコードの出力はどれか。

a = [1, 2]b = [1, 2]c = aprint(a == b, a is b)print(a == c, a is c)
  1. True True と True True
  2. True False と True False
  3. False False と True True
  4. True False と True True
正解と解説
正解:D. True False と True True

== は値が等しいかを尋ねる演算子なので、中身が同じ a と b では True になる。is は同じオブジェクトかを尋ねる演算子で、a と b は別々に作られた2つのリストだから False である。一方 c = a は新しいリストを作らず同じオブジェクトに別名を付けただけなので、a is c は True になる。つまり c を通してリストを書き換えると a からも変化が見える。None は1つしか存在しない特別なオブジェクトなので x is None と書くのが作法だが、値を比べたいときは常に == を使う。

根拠:Python Software Foundation「Python チュートリアル 10. Brief tour of the standard library」Python 3.14 ドキュメント(2026年8月確認)

演習:この章の問題を解く

ランダム出題の演習ツールです(JavaScript が有効な場合に動きます)。上の「確認問題」はそのままでもすべて読めます。

※ 解説は学習用の情報提供です。最新の出題範囲・制度は必ず公式発表をご確認ください。
※ 出題は、AWS公式ドキュメント・試験ガイド、JDLA「G検定 試験出題範囲(シラバス2024)第1.4版」、一般社団法人Pythonエンジニア育成推進協会の公開情報とPython公式ドキュメントに沿った仮の宿 学習室のオリジナル問題です(2026年8月時点で確認)。Pythonの問題はすべて実行して確認しています。試験制度・出題範囲は各実施団体の公式発表をご確認ください。