Python総合演習問題50問
2025-11-30はじめに
この記事では、Pythonの練習問題を初級・中級・上級の3段階、全50問収録しています。それぞれの問題には具体的な入出力条件と解答例コードを掲載しています。コードをそのまま実行して動作を確認しながら学習を進めてください。
🟢 初級問題(問題1〜15)
問題1:基本データ型操作
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 整数
a = 10、浮動小数点数b = 3.14、文字列name = "Python"、ブーリアンflag = Trueを変数として定義する a + bの結果を表示する(型も一緒に表示すること)nameを3回繰り返した文字列を表示するflagの否定(not flag)を表示する
【期待する出力例】
合計: 13.14 (型: <class 'float'>)
繰り返し: PythonPythonPython
flagの否定: False
【解答例】
a = 10
b = 3.14
name = "Python"
flag = True
result = a + b
print(f"合計: {result} (型: {type(result)})")
print(f"繰り返し: {name * 3}")
print(f"flagの否定: {not flag}")
問題2:条件分岐の基本
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 変数
numberに整数値を代入する(例:-5、0、7などで動作確認すること) numberが正の数なら"〇〇は正の数です"、負の数なら"〇〇は負の数です"、ゼロなら"ゼロです"と表示する
【期待する出力例(number = -5 の場合)】
-5は負の数です
【解答例】
number = -5
if number > 0:
print(f"{number}は正の数です")
elif number < 0:
print(f"{number}は負の数です")
else:
print("ゼロです")
問題3:FizzBuzz
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 1から30までの整数をループで処理する
- 3の倍数のときは
Fizz、5の倍数のときはBuzz、3と5の両方の倍数のときはFizzBuzzを表示する - それ以外はその数をそのまま表示する
- すべての出力を1行ずつ表示する
【期待する出力例(最初の16行)】
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
...
【解答例】
for i in range(1, 31):
if i % 15 == 0:
print("FizzBuzz")
elif i % 3 == 0:
print("Fizz")
elif i % 5 == 0:
print("Buzz")
else:
print(i)
問題4:リスト操作
【問題】
以下の条件をすべて満たすプログラムを作成してください。
numbers = [34, 7, 23, 32, 5, 62, 18, 45, 11, 29]というリストを使用する- 組み込み関数(
max()・min()・sum()・len())を使って最大値・最小値・平均値を求め、それぞれ表示する - 平均値は小数点以下2桁で表示する
【期待する出力例】
最大値: 62
最小値: 5
平均値: 26.60
【解答例】
numbers = [34, 7, 23, 32, 5, 62, 18, 45, 11, 29]
print(f"最大値: {max(numbers)}")
print(f"最小値: {min(numbers)}")
print(f"平均値: {sum(numbers) / len(numbers):.2f}")
問題5:辞書の基本操作
【問題】
以下の条件をすべて満たすプログラムを作成してください。
scores = {"Alice": 85, "Bob": 72, "Charlie": 91}という辞書を定義する- キー
"Bob"の点数を検索して表示する "Bob"の点数を80に更新して全体を表示する"Charlie"を削除して全体を表示する- 存在しないキー
"Dave"を検索した場合、"該当者なし"と表示する(get()を使うこと)
【期待する出力例】
Bobの点数: 72
更新後: {'Alice': 85, 'Bob': 80, 'Charlie': 91}
削除後: {'Alice': 85, 'Bob': 80}
Dave: 該当者なし
【解答例】
scores = {"Alice": 85, "Bob": 72, "Charlie": 91}
print(f"Bobの点数: {scores['Bob']}")
scores["Bob"] = 80
print(f"更新後: {scores}")
del scores["Charlie"]
print(f"削除後: {scores}")
print(f"Dave: {scores.get('Dave', '該当者なし')}")
問題6:四則演算関数
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 2つの数値
x・yを引数として受け取り、和・差・積・商をタプルで返す関数calc(x, y)を定義する y == 0のときZeroDivisionErrorを捕捉し、商の部分をNoneで返すcalc(10, 3)とcalc(10, 0)の両方を呼び出して結果を表示する
【期待する出力例】
calc(10, 3) → 和:13, 差:7, 積:30, 商:3.3333333333333335
calc(10, 0) → 和:10, 差:10, 積:0, 商:None
【解答例】
def calc(x, y):
try:
quotient = x / y
except ZeroDivisionError:
quotient = None
return (x + y, x - y, x * y, quotient)
for args in [(10, 3), (10, 0)]:
s, d, p, q = calc(*args)
print(f"calc{args} → 和:{s}, 差:{d}, 積:{p}, 商:{q}")
問題7:ファイル読み込み
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- まずプログラム内で
sample.txtというファイルを作成し、5行以上の文章を書き込む - 次にそのファイルを読み込み、総行数・空行を除いた行数・総文字数(改行除く)を表示する
【期待する出力例】
総行数: 6
空行を除いた行数: 5
総文字数(改行除く): 87
【解答例】
# ファイルを作成
with open("sample.txt", "w", encoding="utf-8") as f:
f.write("Pythonは汎用プログラミング言語です。\n")
f.write("シンプルな文法が特徴です。\n")
f.write("データ分析や機械学習にも使われます。\n")
f.write("Webアプリケーション開発にも活用できます。\n")
f.write("初心者から上級者まで幅広く使われています。\n")
f.write("\n")
# ファイルを読み込んで集計
with open("sample.txt", "r", encoding="utf-8") as f:
lines = f.readlines()
total_lines = len(lines)
non_empty = sum(1 for line in lines if line.strip())
total_chars = sum(len(line.rstrip("\n")) for line in lines)
print(f"総行数: {total_lines}")
print(f"空行を除いた行数: {non_empty}")
print(f"総文字数(改行除く): {total_chars}")
問題8:ファイル書き込み
【問題】
以下の条件をすべて満たすプログラムを作成してください。
notes = ["買い物リスト", "牛乳", "卵", "パン", "りんご"]というリストをあらかじめ定義するoutput.txtに各要素を1行ずつ書き込む- 書き込み後に再度読み込んで内容をそのまま表示し、「〇行書き込みました」と行数を表示する
【期待する出力例】
買い物リスト
牛乳
卵
パン
りんご
5行書き込みました
【解答例】
notes = ["買い物リスト", "牛乳", "卵", "パン", "りんご"]
with open("output.txt", "w", encoding="utf-8") as f:
for note in notes:
f.write(note + "\n")
with open("output.txt", "r", encoding="utf-8") as f:
lines = f.readlines()
for line in lines:
print(line, end="")
print(f"{len(lines)}行書き込みました")
問題9:Personクラスの作成
【問題】
以下の条件をすべて満たすプログラムを作成してください。
name(文字列)とage(整数)を属性として持つPersonクラスを定義するintroduce()メソッドで「私の名前は〇〇です。〇歳です。」と表示するis_adult()メソッドで18歳以上ならTrue、未満ならFalseを返す- 3人分のインスタンスを作成し、それぞれ
introduce()とis_adult()の結果を表示する
【期待する出力例】
私の名前は田中太郎です。25歳です。成人: True
私の名前は鈴木花子です。17歳です。成人: False
私の名前は山田次郎です。18歳です。成人: True
【解答例】
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(f"私の名前は{self.name}です。{self.age}歳です。", end=" ")
def is_adult(self):
return self.age >= 18
people = [
Person("田中太郎", 25),
Person("鈴木花子", 17),
Person("山田次郎", 18),
]
for p in people:
p.introduce()
print(f"成人: {p.is_adult()}")
問題10:例外処理の基礎
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 文字列のリスト
inputs = ["42", "hello", "3.14", "", "100"]を定義する - 各要素を
int()で変換しようとし、ValueErrorが発生した場合は"'〇〇' は整数に変換できません"と表示する - 変換成功した場合は
"変換成功: 〇〇"と表示する
【期待する出力例】
変換成功: 42
'hello' は整数に変換できません
'3.14' は整数に変換できません
'' は整数に変換できません
変換成功: 100
【解答例】
inputs = ["42", "hello", "3.14", "", "100"]
for s in inputs:
try:
val = int(s)
print(f"変換成功: {val}")
except ValueError:
print(f"'{s}' は整数に変換できません")
問題11:リスト内包表記
【問題】
以下の条件をすべて満たすプログラムを作成してください。
range(1, 21)を元に、リスト内包表記1行で偶数のみのリストを作成する- さらにリスト内包表記1行で、そのリストの各要素を2乗したリストも作成する
- 両方のリストを表示する
【期待する出力例】
偶数リスト: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
2乗リスト: [4, 16, 36, 64, 100, 144, 196, 256, 324, 400]
【解答例】
evens = [n for n in range(1, 21) if n % 2 == 0]
squares = [n ** 2 for n in evens]
print(f"偶数リスト: {evens}")
print(f"2乗リスト: {squares}")
問題12:文字列操作
【問題】
以下の条件をすべて満たすプログラムを作成してください。
text = "the quick brown fox jumps over the lazy dog"を使用する- 単語数を数えて表示する
- 各単語の先頭を大文字にした文字列を表示する(
title()は使わず、split()とcapitalize()を使うこと) - 文字列中に "the" が何回登場するかを表示する(大文字小文字は区別しない)
【期待する出力例】
単語数: 9
変換後: The Quick Brown Fox Jumps Over The Lazy Dog
'the'の登場回数: 2
【解答例】
text = "the quick brown fox jumps over the lazy dog"
words = text.split()
print(f"単語数: {len(words)}")
capitalized = " ".join(w.capitalize() for w in words)
print(f"変換後: {capitalized}")
count = text.lower().split().count("the")
print(f"'the'の登場回数: {count}")
問題13:円の計算
【問題】
以下の条件をすべて満たすプログラムを作成してください。
mathモジュールのpi定数を使用する(自分で3.14など定義しないこと)- 半径
r = 5として、円周と面積を計算して表示する - 半径が負の値の場合は
ValueErrorを発生させ、"半径は正の値を入力してください"と表示する r = 5とr = -3両方で動作確認する
【期待する出力例】
半径5の円: 円周=31.42, 面積=78.54
半径は正の値を入力してください
【解答例】
import math
def circle_stats(r):
if r < 0:
raise ValueError("半径は正の値を入力してください")
circumference = 2 * math.pi * r
area = math.pi * r ** 2
return circumference, area
for r in [5, -3]:
try:
c, a = circle_stats(r)
print(f"半径{r}の円: 円周={c:.2f}, 面積={a:.2f}")
except ValueError as e:
print(e)
問題14:日付と時間
【問題】
以下の条件をすべて満たすプログラムを作成してください。
datetimeモジュールを使用する- 現在の日付と時刻を
YYYY年MM月DD日 HH:MM:SSの形式で表示する - 現在から100日後の日付を同じ形式で表示する
- 今日が今年の何日目かを表示する(
timetuple().tm_ydayを使用)
【期待する出力例(実行日による)】
現在: 2025年06月15日 10:30:45
100日後: 2025年09月23日 10:30:45
今年の第166日目
【解答例】
from datetime import datetime, timedelta
now = datetime.now()
future = now + timedelta(days=100)
print(f"現在: {now.strftime('%Y年%m月%d日 %H:%M:%S')}")
print(f"100日後: {future.strftime('%Y年%m月%d日 %H:%M:%S')}")
print(f"今年の第{now.timetuple().tm_yday}日目")
問題15:mathモジュールの活用
【問題】
以下の条件をすべて満たすプログラムを作成してください。
mathモジュールを使用する- 角度リスト
[0, 30, 45, 60, 90]を度数法で定義し、各角度についてsin・cos・tan(tan は90度除く)を計算して表示する - 角度は
math.radians()でラジアンに変換すること - 各値は小数点以下4桁で表示する
【期待する出力例】
角度 sin cos tan
0° 0.0000 1.0000 0.0000
30° 0.5000 0.8660 0.5774
45° 0.7071 0.7071 1.0000
60° 0.8660 0.5000 1.7321
90° 1.0000 0.0000 -
【解答例】
import math
angles = [0, 30, 45, 60, 90]
print(f"{'角度':<5} {'sin':<8} {'cos':<8} {'tan'}")
for deg in angles:
rad = math.radians(deg)
s = math.sin(rad)
c = math.cos(rad)
t = f"{math.tan(rad):.4f}" if deg != 90 else "-"
print(f"{deg}°{'':<3} {s:.4f} {c:.4f} {t}")
🟡 中級問題(問題16〜40)
問題16:BankAccountクラス
【問題】
以下の条件をすべて満たすプログラムを作成してください。
BankAccountクラスを定義し、口座名義(owner)と初期残高(balance、デフォルト0)を属性として持つdeposit(amount): 正の金額のみ受け付け、それ以外はValueErrorを発生させるwithdraw(amount): 残高不足の場合はValueError("残高不足")を発生させるget_balance(): 現在の残高を返す- 一連の操作(入金・出金・残高照会・残高不足の出金)を実行して結果を表示する
【期待する出力例】
入金後残高: 10000
出金後残高: 6500
現在残高: 6500
エラー: 残高不足
【解答例】
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("入金額は正の値でなければなりません")
self.balance += amount
def withdraw(self, amount):
if amount > self.balance:
raise ValueError("残高不足")
self.balance -= amount
def get_balance(self):
return self.balance
account = BankAccount("田中太郎")
account.deposit(10000)
print(f"入金後残高: {account.get_balance()}")
account.withdraw(3500)
print(f"出金後残高: {account.get_balance()}")
print(f"現在残高: {account.get_balance()}")
try:
account.withdraw(10000)
except ValueError as e:
print(f"エラー: {e}")
問題17:継承の実装
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 基底クラス
Vehicleにbrand(メーカー)・speed(最高速度km/h)を属性として持たせ、info()メソッドで基本情報を表示する Car(Vehicle)にnum_doors(ドア数)を追加し、info()をオーバーライドしてドア数も表示するMotorcycle(Vehicle)にhas_sidecar(サイドカーの有無、bool)を追加し、info()をオーバーライドする- 各クラスのインスタンスを1つずつ作成し、
info()を呼び出す
【期待する出力例】
[Car] Toyota | 最高速度: 180km/h | ドア数: 4
[Motorcycle] Honda | 最高速度: 220km/h | サイドカー: なし
【解答例】
class Vehicle:
def __init__(self, brand, speed):
self.brand = brand
self.speed = speed
def info(self):
print(f"[Vehicle] {self.brand} | 最高速度: {self.speed}km/h")
class Car(Vehicle):
def __init__(self, brand, speed, num_doors):
super().__init__(brand, speed)
self.num_doors = num_doors
def info(self):
print(f"[Car] {self.brand} | 最高速度: {self.speed}km/h | ドア数: {self.num_doors}")
class Motorcycle(Vehicle):
def __init__(self, brand, speed, has_sidecar):
super().__init__(brand, speed)
self.has_sidecar = has_sidecar
def info(self):
sidecar = "あり" if self.has_sidecar else "なし"
print(f"[Motorcycle] {self.brand} | 最高速度: {self.speed}km/h | サイドカー: {sidecar}")
Car("Toyota", 180, 4).info()
Motorcycle("Honda", 220, False).info()
問題18:ポリモーフィズムの実装
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 基底クラス
Shapeに抽象的なarea()メソッドを定義する(raise NotImplementedErrorを使う) Circle(Shape):半径rから面積を計算Rectangle(Shape):幅wと高さhから面積を計算Triangle(Shape):底辺baseと高さheightから面積を計算- 3つのインスタンスをリストに格納し、ループで
area()を呼び出して全図形の面積を表示する
【期待する出力例】
Circle: 面積 = 78.54
Rectangle: 面積 = 24.00
Triangle: 面積 = 15.00
【解答例】
import math
class Shape:
def area(self):
raise NotImplementedError("サブクラスで実装してください")
class Circle(Shape):
def __init__(self, r):
self.r = r
def area(self):
return math.pi * self.r ** 2
class Rectangle(Shape):
def __init__(self, w, h):
self.w = w
self.h = h
def area(self):
return self.w * self.h
class Triangle(Shape):
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return self.base * self.height / 2
shapes = [Circle(5), Rectangle(4, 6), Triangle(6, 5)]
for shape in shapes:
print(f"{shape.__class__.__name__}: 面積 = {shape.area():.2f}")
問題19:カプセル化の実装
【問題】
以下の条件をすべて満たすプログラムを作成してください。
Studentクラスを作成し、__name(文字列)と__score(0〜100の整数)をプライベート属性として持たせるnameとscoreのゲッター/セッターを@propertyで定義するscoreのセッターで0未満または100超の値が設定された場合、ValueErrorを発生させる- 正常な操作と不正な操作の両方を実行して確認する
【期待する出力例】
名前: 山田, スコア: 85
スコア更新後: 90
エラー: スコアは0〜100の範囲で入力してください
【解答例】
class Student:
def __init__(self, name, score):
self.__name = name
self.score = score # セッター経由で設定
@property
def name(self):
return self.__name
@name.setter
def name(self, value):
self.__name = value
@property
def score(self):
return self.__score
@score.setter
def score(self, value):
if not (0 <= value <= 100):
raise ValueError("スコアは0〜100の範囲で入力してください")
self.__score = value
s = Student("山田", 85)
print(f"名前: {s.name}, スコア: {s.score}")
s.score = 90
print(f"スコア更新後: {s.score}")
try:
s.score = 150
except ValueError as e:
print(f"エラー: {e}")
問題20:特殊メソッドの活用
【問題】
以下の条件をすべて満たすプログラムを作成してください。
Vector2Dクラスを作成し、xとy座標を属性として持つ__str__:"Vector(x, y)"形式で返す__repr__:"Vector2D(x=〇, y=〇)"形式で返す__add__: 2つのベクトルを加算して新しいVector2Dを返す__len__: ベクトルの成分数(常に2)を返す- 2つのインスタンスを作成して加算し、各特殊メソッドの動作を確認する
【期待する出力例】
str: Vector(1, 2)
repr: Vector2D(x=1, y=2)
v1 + v2: Vector(4, 6)
len: 2
【解答例】
class Vector2D:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"Vector({self.x}, {self.y})"
def __repr__(self):
return f"Vector2D(x={self.x}, y={self.y})"
def __add__(self, other):
return Vector2D(self.x + other.x, self.y + other.y)
def __len__(self):
return 2
v1 = Vector2D(1, 2)
v2 = Vector2D(3, 4)
print(f"str: {v1}")
print(f"repr: {repr(v1)}")
print(f"v1 + v2: {v1 + v2}")
print(f"len: {len(v1)}")
問題21:独自例外の定義
【問題】
以下の条件をすべて満たすプログラムを作成してください。
Exceptionを継承したInsufficientFundsErrorを定義し、不足額を属性として保持するBankAccountクラス(問題16と同様)のwithdraw()メソッドで残高不足時にInsufficientFundsErrorを発生させる- エラー発生時に
"残高不足: 〇〇円不足しています"と不足額を表示する
【期待する出力例】
残高不足: 2000円不足しています
【解答例】
class InsufficientFundsError(Exception):
def __init__(self, shortage):
self.shortage = shortage
super().__init__(f"残高不足: {shortage}円不足しています")
class BankAccount:
def __init__(self, balance=0):
self.balance = balance
def withdraw(self, amount):
if amount > self.balance:
raise InsufficientFundsError(amount - self.balance)
self.balance -= amount
account = BankAccount(3000)
try:
account.withdraw(5000)
except InsufficientFundsError as e:
print(e)
問題22:デコレータの作成
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 関数の実行時間を計測して
"〇〇: 〇.〇〇〇〇秒"と表示するデコレータtimerを作成する functools.wrapsを使って元の関数名を保持する- 1〜10000の合計を計算する関数と、0.1秒スリープする関数の2つに
@timerを適用して実行する
【期待する出力例】
sum_numbers: 0.0003秒
合計: 50005000
slow_function: 0.1001秒
【解答例】
import time
import functools
def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"{func.__name__}: {elapsed:.4f}秒")
return result
return wrapper
@timer
def sum_numbers(n):
return sum(range(n + 1))
@timer
def slow_function():
time.sleep(0.1)
result = sum_numbers(10000)
print(f"合計: {result}")
slow_function()
問題23:フィボナッチジェネレータ
【問題】
以下の条件をすべて満たすプログラムを作成してください。
yieldを使ったジェネレータ関数fibonacci(n)を作成し、n番目までのフィボナッチ数列を生成するfibonacci(10)で最初の10個の値をリストとして取得し表示する- ジェネレータを使って50を超える最初のフィボナッチ数を
next()を使わずにforループで見つけて表示する
【期待する出力例】
最初の10個: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
50を超える最初の値: 55
【解答例】
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
print(f"最初の10個: {list(fibonacci(10))}")
for val in fibonacci(20):
if val > 50:
print(f"50を超える最初の値: {val}")
break
問題24:コンテキストマネージャ
【問題】
以下の条件をすべて満たすプログラムを作成してください。
__enter__と__exit__を実装したクラスManagedFileを作成する- ファイルを開く際に
"ファイルを開きました: 〇〇"、閉じる際に"ファイルを閉じました: 〇〇"と表示する __exit__で例外が発生した場合のログも出力するwith ManagedFile("test.txt") as f:の形式で使用できることを確認する
【期待する出力例】
ファイルを開きました: test.txt
書き込み完了
ファイルを閉じました: test.txt
【解答例】
class ManagedFile:
def __init__(self, filename, mode="w", encoding="utf-8"):
self.filename = filename
self.mode = mode
self.encoding = encoding
self.file = None
def __enter__(self):
print(f"ファイルを開きました: {self.filename}")
self.file = open(self.filename, self.mode, encoding=self.encoding)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
print(f"例外発生: {exc_val}")
if self.file:
self.file.close()
print(f"ファイルを閉じました: {self.filename}")
return False # 例外を伝播させる
with ManagedFile("test.txt") as f:
f.write("Hello, Context Manager!\n")
print("書き込み完了")
問題25:ログ出力の実装
【問題】
以下の条件をすべて満たすプログラムを作成してください。
loggingモジュールを使用し、ログレベルDEBUG以上をapp.logファイルに出力するよう設定する- フォーマットは
[%(levelname)s] %(asctime)s - %(message)sとする DEBUG・INFO・WARNING・ERROR・CRITICAL各レベルのメッセージを1つずつ出力する- 最後に
app.logを読み込んで内容を表示する
【期待する出力例(ファイル内容)】
[DEBUG] 2025-06-15 10:00:00,000 - デバッグ情報
[INFO] 2025-06-15 10:00:00,001 - 処理開始
[WARNING] 2025-06-15 10:00:00,002 - 注意が必要です
[ERROR] 2025-06-15 10:00:00,003 - エラーが発生しました
[CRITICAL] 2025-06-15 10:00:00,004 - 致命的なエラーです
【解答例】
import logging
logging.basicConfig(
filename="app.log",
level=logging.DEBUG,
format="[%(levelname)s] %(asctime)s - %(message)s",
encoding="utf-8"
)
logging.debug("デバッグ情報")
logging.info("処理開始")
logging.warning("注意が必要です")
logging.error("エラーが発生しました")
logging.critical("致命的なエラーです")
with open("app.log", "r", encoding="utf-8") as f:
print(f.read())
問題26:JSONデータの処理
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 以下の辞書データを
students.jsonに保存する(インデント=2、日本語はそのまま保存)
{"students": [{"name": "Alice", "score": 85}, {"name": "Bob", "score": 72}, {"name": "Charlie", "score": 91}]} - 保存したファイルを読み込み、スコアが80以上の学生名だけをリストで表示する
【期待する出力例】
80以上の学生: ['Alice', 'Charlie']
【解答例】
import json
data = {
"students": [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 72},
{"name": "Charlie", "score": 91}
]
}
with open("students.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
with open("students.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
high_scorers = [s["name"] for s in loaded["students"] if s["score"] >= 80]
print(f"80以上の学生: {high_scorers}")
問題27:CSVデータの操作
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 以下のデータを
products.csvとして作成する:
ヘッダー:name,price,quantity
データ: Apple/150/10, Banana/80/25, Cherry/300/5, Grape/500/8 - CSVを読み込み、各商品の合計金額(price × quantity)を計算して新しい列
totalを加えたproducts_updated.csvを出力する - 更新後のCSVの内容を表示する
【期待する出力例】
name,price,quantity,total
Apple,150,10,1500
Banana,80,25,2000
Cherry,300,5,1500
Grape,500,8,4000
【解答例】
import csv
rows = [
["name", "price", "quantity"],
["Apple", 150, 10],
["Banana", 80, 25],
["Cherry", 300, 5],
["Grape", 500, 8],
]
with open("products.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerows(rows)
with open("products.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
updated = []
for row in reader:
row["total"] = int(row["price"]) * int(row["quantity"])
updated.append(row)
fieldnames = ["name", "price", "quantity", "total"]
with open("products_updated.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(updated)
with open("products_updated.csv", "r", encoding="utf-8") as f:
print(f.read())
問題28:SQLiteデータベース接続
【問題】
以下の条件をすべて満たすプログラムを作成してください。
school.dbに接続し、studentsテーブルを作成する(カラム:id INTEGER PRIMARY KEY AUTOINCREMENT・name TEXT・grade INTEGER・score REAL)- テーブルが既に存在する場合はエラーにならないようにする(
CREATE TABLE IF NOT EXISTS) - 3件のデータを INSERT し、全件を SELECT して表示する
【期待する出力例】
id=1, name=田中, grade=2, score=85.5
id=2, name=鈴木, grade=3, score=91.0
id=3, name=佐藤, grade=1, score=78.0
【解答例】
import sqlite3
conn = sqlite3.connect("school.db")
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS students (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
grade INTEGER,
score REAL
)
""")
students = [("田中", 2, 85.5), ("鈴木", 3, 91.0), ("佐藤", 1, 78.0)]
cur.executemany("INSERT INTO students (name, grade, score) VALUES (?, ?, ?)", students)
conn.commit()
for row in cur.execute("SELECT * FROM students"):
print(f"id={row[0]}, name={row[1]}, grade={row[2]}, score={row[3]}")
conn.close()
問題29:CRUD操作の実装
【問題】
問題28で作成した school.db の students テーブルに対して、以下のCRUD操作をすべて実装してください。
- Create: 新しい学生を1件追加する関数
create_student(conn, name, grade, score) - Read: 全件取得する
read_all(conn)と、idで1件取得するread_by_id(conn, id) - Update: 指定
idのscoreを更新するupdate_score(conn, id, score) - Delete: 指定
idを削除するdelete_student(conn, id) - 各関数を順番に呼び出して動作を確認する
【期待する出力例】
追加後全件: [(1, '山田', 1, 88.0)]
id=1: (1, '山田', 1, 88.0)
更新後: (1, '山田', 1, 95.0)
削除後全件: []
【解答例】
import sqlite3
def get_connection():
conn = sqlite3.connect(":memory:")
conn.execute("""CREATE TABLE students
(id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT, grade INTEGER, score REAL)""")
return conn
def create_student(conn, name, grade, score):
conn.execute("INSERT INTO students (name, grade, score) VALUES (?, ?, ?)",
(name, grade, score))
conn.commit()
def read_all(conn):
return conn.execute("SELECT * FROM students").fetchall()
def read_by_id(conn, id):
return conn.execute("SELECT * FROM students WHERE id=?", (id,)).fetchone()
def update_score(conn, id, score):
conn.execute("UPDATE students SET score=? WHERE id=?", (score, id))
conn.commit()
def delete_student(conn, id):
conn.execute("DELETE FROM students WHERE id=?", (id,))
conn.commit()
conn = get_connection()
create_student(conn, "山田", 1, 88.0)
print(f"追加後全件: {read_all(conn)}")
print(f"id=1: {read_by_id(conn, 1)}")
update_score(conn, 1, 95.0)
print(f"更新後: {read_by_id(conn, 1)}")
delete_student(conn, 1)
print(f"削除後全件: {read_all(conn)}")
conn.close()
問題30:データ永続化クラス
【問題】
以下の条件をすべて満たすプログラムを作成してください。
UserSettingsクラスを作成し、settings.jsonにユーザー設定を読み書きするget(key, default=None): キーの値を返す(存在しない場合はdefault)set(key, value): キーと値を設定してファイルに即保存delete(key): キーを削除してファイルに即保存- インスタンスを2回作成しても設定が引き継がれることを確認する
【期待する出力例】
theme: dark
language: ja
theme削除後: None
再起動後のlanguage: ja
【解答例】
import json
import os
class UserSettings:
def __init__(self, filepath="settings.json"):
self.filepath = filepath
self._data = {}
if os.path.exists(filepath):
with open(filepath, "r", encoding="utf-8") as f:
self._data = json.load(f)
def _save(self):
with open(self.filepath, "w", encoding="utf-8") as f:
json.dump(self._data, f, ensure_ascii=False, indent=2)
def get(self, key, default=None):
return self._data.get(key, default)
def set(self, key, value):
self._data[key] = value
self._save()
def delete(self, key):
self._data.pop(key, None)
self._save()
s1 = UserSettings()
s1.set("theme", "dark")
s1.set("language", "ja")
print(f"theme: {s1.get('theme')}")
print(f"language: {s1.get('language')}")
s1.delete("theme")
print(f"theme削除後: {s1.get('theme')}")
s2 = UserSettings()
print(f"再起動後のlanguage: {s2.get('language')}")
問題31:HTTPリクエストの送信
【問題】
以下の条件をすべて満たすプログラムを作成してください。
requestsライブラリを使用してhttps://jsonplaceholder.typicode.com/posts/1にGETリクエストを送信する- ステータスコードを表示する
- レスポンスのJSONから
userId・title・bodyを取り出して表示する - 接続エラーの場合は
requests.exceptions.ConnectionErrorを捕捉してメッセージを表示する
【期待する出力例】
ステータスコード: 200
userId: 1
title: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
body: quia et suscipit...
【解答例】
import requests
url = "https://jsonplaceholder.typicode.com/posts/1"
try:
response = requests.get(url, timeout=10)
print(f"ステータスコード: {response.status_code}")
data = response.json()
print(f"userId: {data['userId']}")
print(f"title: {data['title']}")
print(f"body: {data['body'][:30]}...")
except requests.exceptions.ConnectionError:
print("接続エラーが発生しました")
問題32:REST APIクライアント
【問題】
以下の条件をすべて満たすプログラムを作成してください。
https://jsonplaceholder.typicode.com/usersから全ユーザーを取得する- 取得したユーザーの中から
usernameが5文字以上のユーザーのみを絞り込む - 絞り込んだユーザーの
name・username・emailを一覧表示する - 総ユーザー数と絞り込み後の件数を表示する
【期待する出力例(一部)】
総ユーザー数: 10 / 絞り込み後: 8
Leanne Graham (Bret) - Sincere@april.biz
...
【解答例】
import requests
response = requests.get("https://jsonplaceholder.typicode.com/users", timeout=10)
users = response.json()
filtered = [u for u in users if len(u["username"]) >= 5]
print(f"総ユーザー数: {len(users)} / 絞り込み後: {len(filtered)}")
for u in filtered:
print(f"{u['name']} ({u['username']}) - {u['email']}")
問題33:データ可視化の基礎
【問題】
以下の条件をすべて満たすプログラムを作成してください。
matplotlibを使用して1つの Figure に2つのサブプロット(1行2列)を作成する- 左:
x = [1,2,3,4,5]、y = [2,4,1,3,5]の折れ線グラフ(タイトル: "折れ線グラフ"、マーカー付き) - 右: 科目と点数のデータ(国語:80, 数学:65, 英語:90, 理科:75, 社会:85)の棒グラフ(タイトル: "科目別点数")
graph.pngとして保存する
【解答例】
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['font.family'] = 'IPAexGothic' # 日本語フォント(環境に合わせて変更)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
x = [1, 2, 3, 4, 5]
y = [2, 4, 1, 3, 5]
ax1.plot(x, y, marker="o")
ax1.set_title("折れ線グラフ")
subjects = ["国語", "数学", "英語", "理科", "社会"]
scores = [80, 65, 90, 75, 85]
ax2.bar(subjects, scores)
ax2.set_title("科目別点数")
plt.tight_layout()
plt.savefig("graph.png")
print("graph.png を保存しました")
問題34:Pandasによるデータ分析
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 以下のデータを持つCSVファイル
exam.csvを作成する(列:name, math, english, science、5名分のデータ) pandasで読み込み、describe()で基本統計量を表示する- 各生徒の合計点と平均点を新列として追加して表示する
- 合計点が最も高い生徒の名前を表示する
【期待する出力例】
name math english science total avg
0 Alice 80 90 85 255 85.00
1 Bob 70 65 80 215 71.67
...
最高得点者: Alice
【解答例】
import pandas as pd
data = {
"name": ["Alice", "Bob", "Charlie", "Diana", "Eve"],
"math": [80, 70, 90, 60, 75],
"english": [90, 65, 85, 70, 95],
"science": [85, 80, 70, 65, 88],
}
df = pd.DataFrame(data)
df.to_csv("exam.csv", index=False)
df = pd.read_csv("exam.csv")
print(df.describe())
subjects = ["math", "english", "science"]
df["total"] = df[subjects].sum(axis=1)
df["avg"] = df[subjects].mean(axis=1).round(2)
print(df)
best = df.loc[df["total"].idxmax(), "name"]
print(f"最高得点者: {best}")
問題35:正規表現の活用
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 以下のテキストからメールアドレスと日本の電話番号(ハイフン区切り、市外局番含む)をすべて抽出する
- テキスト例:
"連絡先: alice@example.com, 電話: 03-1234-5678, bob.smith@test.co.jp, 090-9876-5432" - 抽出した結果をそれぞれリストで表示する
【期待する出力例】
メールアドレス: ['alice@example.com', 'bob.smith@test.co.jp']
電話番号: ['03-1234-5678', '090-9876-5432']
【解答例】
import re
text = "連絡先: alice@example.com, 電話: 03-1234-5678, bob.smith@test.co.jp, 090-9876-5432"
emails = re.findall(r'[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}', text)
phones = re.findall(r'\d{2,4}-\d{3,4}-\d{4}', text)
print(f"メールアドレス: {emails}")
print(f"電話番号: {phones}")
問題36:マルチスレッド処理
【問題】
以下の条件をすべて満たすプログラムを作成してください。
threading.Threadを使い、0.5秒スリープして"タスク〇〇 完了"と表示する関数task(name)を定義する- タスクA・B・Cを3つのスレッドで同時に起動する
- 全スレッドが完了してから
"すべてのタスクが完了しました"と表示する(join()を使うこと) - スレッドなしの逐次実行と比べて実行時間が短くなっていることを確認するため、開始・終了時刻を表示する
【期待する出力例】
開始
タスクB 完了
タスクA 完了
タスクC 完了
すべてのタスクが完了しました
経過時間: 0.50秒
【解答例】
import threading
import time
def task(name):
time.sleep(0.5)
print(f"タスク{name} 完了")
start = time.time()
print("開始")
threads = [threading.Thread(target=task, args=(n,)) for n in ["A", "B", "C"]]
for t in threads:
t.start()
for t in threads:
t.join()
print("すべてのタスクが完了しました")
print(f"経過時間: {time.time() - start:.2f}秒")
問題37:イテレータの実装
【問題】
以下の条件をすべて満たすプログラムを作成してください。
__iter__と__next__を実装したCountdownクラスを作成する- コンストラクタで開始値
startを受け取り、startから0までの整数を順番に返す - 0以下になったら
StopIterationを発生させる Countdown(5)をforループで使用して出力する
【期待する出力例】
5
4
3
2
1
0
【解答例】
class Countdown:
def __init__(self, start):
self.current = start
def __iter__(self):
return self
def __next__(self):
if self.current < 0:
raise StopIteration
val = self.current
self.current -= 1
return val
for n in Countdown(5):
print(n)
問題38:プロパティの使用
【問題】
以下の条件をすべて満たすプログラムを作成してください。
Temperatureクラスを作成し、内部では摂氏(_celsius)で温度を保持するcelsiusプロパティ: ゲッターとセッターを実装し、セッターでは −273.15未満の値をValueErrorで拒否するfahrenheitプロパティ: ゲッターのみ実装し、摂氏からの変換値を返す(°C × 9/5 + 32)- 100℃・−300℃(エラー確認)・0℃ の3パターンで動作確認する
【期待する出力例】
100℃ = 212.0°F
エラー: -273.15未満の温度は存在しません
0℃ = 32.0°F
【解答例】
class Temperature:
def __init__(self, celsius=0):
self.celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("-273.15未満の温度は存在しません")
self._celsius = value
@property
def fahrenheit(self):
return self._celsius * 9 / 5 + 32
for c in [100, -300, 0]:
try:
t = Temperature(c)
print(f"{c}℃ = {t.fahrenheit}°F")
except ValueError as e:
print(f"エラー: {e}")
問題39:モックオブジェクトの使用
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 外部API(
requests.get)を呼び出す関数fetch_user(user_id)を作成する(戻り値は{"id": user_id, "name": "..."}の辞書) unittest.mock.patchを使ってrequests.getをモック化し、実際のHTTPリクエストを発生させずにテストを書くunittest.TestCaseを継承したテストクラスを作成し、正常レスポンスのテストケースを最低1つ実装する
【期待する出力例】
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
【解答例】
import unittest
from unittest.mock import patch, MagicMock
import requests
def fetch_user(user_id):
response = requests.get(f"https://api.example.com/users/{user_id}")
return response.json()
class TestFetchUser(unittest.TestCase):
@patch("requests.get")
def test_fetch_user_success(self, mock_get):
mock_response = MagicMock()
mock_response.json.return_value = {"id": 1, "name": "Alice"}
mock_get.return_value = mock_response
result = fetch_user(1)
mock_get.assert_called_once_with("https://api.example.com/users/1")
self.assertEqual(result["id"], 1)
self.assertEqual(result["name"], "Alice")
if __name__ == "__main__":
unittest.main()
問題40:パッケージ作成
【問題】
以下の条件をすべて満たすパッケージを作成してください。
- パッケージ名:
mathutils mathutils/basic.py:add・subtract・multiply・divide関数を実装(divideはゼロ除算でValueError)mathutils/stats.py:mean・median・mode関数を実装(標準ライブラリのみ使用)mathutils/__init__.py: 両モジュールから全関数をインポートしてパッケージ直下から使えるようにする- パッケージ外から
from mathutils import add, meanの形式でインポートして動作確認する
【期待する出力例】
add(3,4) = 7
mean([1,2,3,4,5]) = 3.0
median([3,1,4,1,5]) = 3
mode([1,2,2,3]) = 2
【解答例】
# mathutils/basic.py
def add(a, b): return a + b
def subtract(a, b): return a - b
def multiply(a, b): return a * b
def divide(a, b):
if b == 0:
raise ValueError("ゼロ除算エラー")
return a / b
# mathutils/stats.py
import statistics
def mean(data): return statistics.mean(data)
def median(data): return statistics.median(data)
def mode(data): return statistics.mode(data)
# mathutils/__init__.py
from .basic import add, subtract, multiply, divide
from .stats import mean, median, mode
# main.py(パッケージ外)
from mathutils import add, mean, median, mode
print(f"add(3,4) = {add(3, 4)}")
print(f"mean([1,2,3,4,5]) = {mean([1,2,3,4,5])}")
print(f"median([3,1,4,1,5]) = {median([3,1,4,1,5])}")
print(f"mode([1,2,2,3]) = {mode([1,2,2,3])}")
🔴 上級問題(問題41〜50)
問題41:Flaskによる簡単なWebアプリ
【問題】
以下の条件をすべて満たすFlaskアプリケーションを作成してください。
- ルート
/:"Hello, Flask!"を返す - ルート
/greet/<name>:"こんにちは、〇〇さん!"を返す - ルート
/calc: クエリパラメータa・b・op(add/sub/mul/div)を受け取り計算結果をJSONで返す - 例:
/calc?a=10&b=3&op=add→{"result": 13} debug=False、port=5000で起動するコードを含める
【解答例】
from flask import Flask, jsonify, request
app = Flask(__name__)
@app.route("/")
def index():
return "Hello, Flask!"
@app.route("/greet/<name>")
def greet(name):
return f"こんにちは、{name}さん!"
@app.route("/calc")
def calc():
a = float(request.args.get("a", 0))
b = float(request.args.get("b", 0))
op = request.args.get("op", "add")
ops = {"add": a + b, "sub": a - b, "mul": a * b}
if op == "div":
if b == 0:
return jsonify({"error": "ゼロ除算"}), 400
result = a / b
else:
result = ops.get(op)
if result is None:
return jsonify({"error": "不正な演算子"}), 400
return jsonify({"result": result})
if __name__ == "__main__":
app.run(debug=False, port=5000)
問題42:asyncioによる非同期処理
【問題】
以下の条件をすべて満たすプログラムを作成してください。
asyncioを使用して、asyncio.sleep()で待機をシミュレートする非同期タスクを作成する- タスク:
fetch_data(name, delay)(delay秒待機後に"name のデータ取得完了"を返す) - タスクA(2秒)、タスクB(1秒)、タスクC(1.5秒)を
asyncio.gather()で並列実行する - 全タスクを合計した実行時間が約2秒(逐次実行なら4.5秒)になることをコメントで示す
【期待する出力例】
タスクB のデータ取得完了
タスクC のデータ取得完了
タスクA のデータ取得完了
総実行時間: 2.00秒
【解答例】
import asyncio
import time
async def fetch_data(name, delay):
await asyncio.sleep(delay)
msg = f"{name} のデータ取得完了"
print(msg)
return msg
async def main():
start = time.time()
# 並列実行: 最長タスク(2秒)が律速 → 合計約2秒
results = await asyncio.gather(
fetch_data("タスクA", 2),
fetch_data("タスクB", 1),
fetch_data("タスクC", 1.5),
)
print(f"総実行時間: {time.time() - start:.2f}秒")
asyncio.run(main())
問題43:SQLAlchemyによるORM
【問題】
以下の条件をすべて満たすプログラムを作成してください。
SQLAlchemyのDeclarativeBaseを使ってProductモデルを定義する(カラム:id・name・price・stock)- インメモリのSQLite(
sqlite:///:memory:)を使用する - 3件のProductを追加し、価格が1000円以上のもののみを取得して表示する
- 最後に全商品の平均価格を
func.avg()を使って表示する
【期待する出力例】
1000円以上の商品:
ノートPC: 80000円 (在庫: 10)
スマートフォン: 50000円 (在庫: 25)
全商品の平均価格: 43666.67円
【解答例】
from sqlalchemy import create_engine, Column, Integer, String, Float, func
from sqlalchemy.orm import DeclarativeBase, Session
engine = create_engine("sqlite:///:memory:")
class Base(DeclarativeBase):
pass
class Product(Base):
__tablename__ = "products"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String)
price = Column(Float)
stock = Column(Integer)
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add_all([
Product(name="ノートPC", price=80000, stock=10),
Product(name="マウス", price=1000, stock=100),
Product(name="スマートフォン", price=50000, stock=25),
])
session.commit()
print("1000円以上の商品:")
for p in session.query(Product).filter(Product.price >= 1000).all():
print(f" {p.name}: {p.price:.0f}円 (在庫: {p.stock})")
avg = session.query(func.avg(Product.price)).scalar()
print(f"全商品の平均価格: {avg:.2f}円")
問題44:Flask REST APIサーバー
【問題】
Flaskを使って、以下のエンドポイントを持つTodoリスト管理APIを実装してください。
GET /todos: 全Todoを返すPOST /todos: JSONボディ{"title": "..."}でTodoを追加し、追加したデータをステータス201で返すPUT /todos/<id>: 指定IDのTodoのdoneをTrueに更新するDELETE /todos/<id>: 指定IDのTodoを削除する- データはメモリ上のリストで管理する(DBは不要)
【解答例】
from flask import Flask, jsonify, request, abort
app = Flask(__name__)
todos = []
next_id = 1
@app.route("/todos", methods=["GET"])
def get_todos():
return jsonify(todos)
@app.route("/todos", methods=["POST"])
def create_todo():
global next_id
data = request.get_json()
if not data or "title" not in data:
abort(400)
todo = {"id": next_id, "title": data["title"], "done": False}
todos.append(todo)
next_id += 1
return jsonify(todo), 201
@app.route("/todos/<int:todo_id>", methods=["PUT"])
def complete_todo(todo_id):
todo = next((t for t in todos if t["id"] == todo_id), None)
if not todo:
abort(404)
todo["done"] = True
return jsonify(todo)
@app.route("/todos/<int:todo_id>", methods=["DELETE"])
def delete_todo(todo_id):
global todos
original = len(todos)
todos = [t for t in todos if t["id"] != todo_id]
if len(todos) == original:
abort(404)
return "", 204
if __name__ == "__main__":
app.run(debug=False, port=5000)
問題45:包括的なユニットテスト
【問題】
以下の条件をすべて満たすテストスイートを作成してください。
- 問題6の
calc()関数に対してunittestで以下のテストケースを実装する - 正常系:
calc(10, 2)の和・差・積・商がすべて正しいこと - 正常系:
calc(0, 5)・calc(-3, 7)のそれぞれの和が正しいこと - 異常系:
calc(10, 0)の商がNoneになること - テストを実行して全テストがパスすることを確認する
【期待する出力例】
......
----------------------------------------------------------------------
Ran 5 tests in 0.001s
OK
【解答例】
import unittest
def calc(x, y):
try:
quotient = x / y
except ZeroDivisionError:
quotient = None
return (x + y, x - y, x * y, quotient)
class TestCalc(unittest.TestCase):
def test_basic_operations(self):
s, d, p, q = calc(10, 2)
self.assertEqual(s, 12)
self.assertEqual(d, 8)
self.assertEqual(p, 20)
self.assertAlmostEqual(q, 5.0)
def test_zero_numerator(self):
s, _, _, _ = calc(0, 5)
self.assertEqual(s, 5)
def test_negative(self):
s, _, _, _ = calc(-3, 7)
self.assertEqual(s, 4)
def test_zero_division_returns_none(self):
_, _, _, q = calc(10, 0)
self.assertIsNone(q)
def test_negative_result(self):
_, d, _, _ = calc(3, 10)
self.assertEqual(d, -7)
if __name__ == "__main__":
unittest.main()
問題46:デザインパターンの実装
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- Observerパターンを実装する
EventEmitterクラス:subscribe(event, callback)・unsubscribe(event, callback)・emit(event, data)メソッドを持つ- 同一イベントに複数のコールバックを登録できること
"click"イベントと"input"イベントにそれぞれコールバックを登録し、emitを呼び出して動作を確認するunsubscribe後に同イベントをemitしても解除したコールバックが呼ばれないことを確認する
【期待する出力例】
[Logger] click: {'x': 100, 'y': 200}
[UI] ボタンがクリックされました
[Input] 入力値: hello
unsubscribe後:
[UI] ボタンがクリックされました
【解答例】
from collections import defaultdict
class EventEmitter:
def __init__(self):
self._listeners = defaultdict(list)
def subscribe(self, event, callback):
self._listeners[event].append(callback)
def unsubscribe(self, event, callback):
self._listeners[event] = [
cb for cb in self._listeners[event] if cb != callback
]
def emit(self, event, data=None):
for callback in self._listeners[event]:
callback(data)
emitter = EventEmitter()
def logger(data):
print(f"[Logger] click: {data}")
def ui_handler(data):
print("[UI] ボタンがクリックされました")
def input_handler(data):
print(f"[Input] 入力値: {data}")
emitter.subscribe("click", logger)
emitter.subscribe("click", ui_handler)
emitter.subscribe("input", input_handler)
emitter.emit("click", {"x": 100, "y": 200})
emitter.emit("input", "hello")
emitter.unsubscribe("click", logger)
print("unsubscribe後:")
emitter.emit("click", {"x": 50, "y": 75})
問題47:データ可視化ダッシュボード
【問題】
以下の条件をすべて満たすプログラムを作成してください。
matplotlibを使って2行2列(4サブプロット)のダッシュボードを作成する- ①月別売上の折れ線グラフ(1〜12月)
- ②カテゴリ別売上シェアの円グラフ(食品30%・家電40%・衣料20%・その他10%)
- ③商品別在庫の棒グラフ(5商品)
- ④売上と在庫の散布図(ランダムデータ20件、
numpy.random.seed(42)使用) - 全体タイトルを
suptitleで設定し、dashboard.pngとして保存する
【解答例】
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
matplotlib.rcParams['font.family'] = 'IPAexGothic'
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
fig.suptitle("販売ダッシュボード", fontsize=16)
# ①折れ線グラフ
months = range(1, 13)
sales = [120, 135, 150, 140, 160, 180, 200, 195, 170, 155, 140, 210]
axes[0, 0].plot(months, sales, marker="o")
axes[0, 0].set_title("月別売上")
axes[0, 0].set_xlabel("月")
# ②円グラフ
labels = ["食品", "家電", "衣料", "その他"]
sizes = [30, 40, 20, 10]
axes[0, 1].pie(sizes, labels=labels, autopct="%1.1f%%")
axes[0, 1].set_title("カテゴリ別シェア")
# ③棒グラフ
products = ["商品A", "商品B", "商品C", "商品D", "商品E"]
stock = [50, 30, 80, 20, 60]
axes[1, 0].bar(products, stock)
axes[1, 0].set_title("商品別在庫")
# ④散布図
np.random.seed(42)
x = np.random.randint(100, 500, 20)
y = np.random.randint(10, 100, 20)
axes[1, 1].scatter(x, y, alpha=0.7)
axes[1, 1].set_title("売上 vs 在庫")
axes[1, 1].set_xlabel("売上")
axes[1, 1].set_ylabel("在庫")
plt.tight_layout()
plt.savefig("dashboard.png")
print("dashboard.png を保存しました")
問題48:機械学習の基礎(線形回帰)
【問題】
以下の条件をすべて満たすプログラムを作成してください。
scikit-learnを使用して、住宅面積から価格を予測する線形回帰モデルを作成する- データ: 面積(㎡)=
[30, 45, 60, 75, 90, 105, 120]、価格(万円)=[1500, 2200, 2800, 3500, 4100, 4800, 5500] - データを訓練データ(80%)とテストデータ(20%)に分割する(
random_state=42) - モデルを訓練し、テストデータでの平均絶対誤差(MAE)と R² スコアを表示する
- 面積
80㎡の予測価格を表示する
【期待する出力例】
MAE: 〇〇.〇〇万円
R²スコア: 0.99
80㎡の予測価格: 〇〇〇〇.〇〇万円
【解答例】
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, r2_score
X = np.array([30, 45, 60, 75, 90, 105, 120]).reshape(-1, 1)
y = np.array([1500, 2200, 2800, 3500, 4100, 4800, 5500])
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(f"MAE: {mean_absolute_error(y_test, y_pred):.2f}万円")
print(f"R²スコア: {r2_score(y_test, y_pred):.2f}")
pred_80 = model.predict([[80]])[0]
print(f"80㎡の予測価格: {pred_80:.2f}万円")
問題49:パフォーマンス最適化
【問題】
以下の条件をすべて満たすプログラムを作成してください。
- 1〜1,000,000 の素数をすべて求める関数を2種類実装する
find_primes_naive(n): 各数について2〜√nまで割り算するナイーブな方法find_primes_sieve(n): エラトステネスの篩(numpy使用可)
- 両方の実行時間を計測して表示する
- 両方の結果が一致することを
assertで確認する - 改善率(何倍速いか)を表示する
【期待する出力例】
ナイーブ法: 3.5234秒 (78498個の素数)
篩法: 0.0512秒 (78498個の素数)
改善率: 68.8倍
【解答例】
import time
import math
import numpy as np
def find_primes_naive(n):
primes = []
for num in range(2, n + 1):
is_prime = True
for i in range(2, int(math.sqrt(num)) + 1):
if num % i == 0:
is_prime = False
break
if is_prime:
primes.append(num)
return primes
def find_primes_sieve(n):
sieve = np.ones(n + 1, dtype=bool)
sieve[0] = sieve[1] = False
for i in range(2, int(math.sqrt(n)) + 1):
if sieve[i]:
sieve[i*i::i] = False
return list(np.where(sieve)[0])
N = 1_000_000
start = time.time()
naive_result = find_primes_naive(N)
t_naive = time.time() - start
start = time.time()
sieve_result = find_primes_sieve(N)
t_sieve = time.time() - start
assert naive_result == sieve_result, "結果が一致しません"
print(f"ナイーブ法: {t_naive:.4f}秒 ({len(naive_result)}個の素数)")
print(f"篩法: {t_sieve:.4f}秒 ({len(sieve_result)}個の素数)")
print(f"改善率: {t_naive / t_sieve:.1f}倍")
問題50:総合プロジェクト — データ管理Webアプリ
【問題】
以下の条件をすべて満たす、Flaskを使ったタスク管理Webアプリケーションを作成してください。
- バックエンド(Flask)
- SQLiteを使ってタスクを永続化する(カラム:
id・title・done・created_at) - REST API:
GET /api/tasks・POST /api/tasks・PUT /api/tasks/<id>・DELETE /api/tasks/<id>
- SQLiteを使ってタスクを永続化する(カラム:
- フロントエンド
- Flask の
render_templateでHTMLを返し、JavaScriptのfetchAPIでバックエンドと通信する - タスク一覧表示・追加・完了チェック・削除ができること
- Flask の
- その他
- ログ出力(
loggingモジュール)を含める - 入力バリデーション(空のタスク名を拒否)を実装する
- ログ出力(
【解答例】
# app.py
import sqlite3
import logging
from datetime import datetime
from flask import Flask, jsonify, request, render_template_string, abort
logging.basicConfig(level=logging.INFO, format="[%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
app = Flask(__name__)
DB = "tasks.db"
def get_db():
conn = sqlite3.connect(DB)
conn.row_factory = sqlite3.Row
return conn
def init_db():
with get_db() as conn:
conn.execute("""CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
done INTEGER DEFAULT 0,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)""")
HTML = """
<!DOCTYPE html>
<html lang="ja"><head><meta charset="UTF-8">
<title>タスク管理</title>
<style>body{font-family:sans-serif;max-width:600px;margin:40px auto}
.done{text-decoration:line-through;color:#aaa}
button{cursor:pointer}</style>
</head><body>
<h1>📋 タスク管理アプリ</h1>
<input id="title" placeholder="タスクを入力..." style="width:70%">
<button onclick="addTask()">追加</button>
<ul id="list"></ul>
<script>
async function load(){
const res = await fetch('/api/tasks');
const tasks = await res.json();
document.getElementById('list').innerHTML = tasks.map(t =>
`<li><input type="checkbox" ${t.done?'checked':''} onchange="toggle(${t.id})">
<span class="${t.done?'done':''}">${t.title}</span>
<button onclick="del(${t.id})">削除</button></li>`
).join('');
}
async function addTask(){
const title = document.getElementById('title').value.trim();
if(!title) return alert('タスク名を入力してください');
await fetch('/api/tasks',{method:'POST',headers:{'Content-Type':'application/json'},
body:JSON.stringify({title})});
document.getElementById('title').value='';
load();
}
async function toggle(id){
await fetch(`/api/tasks/${id}`,{method:'PUT'});
load();
}
async function del(id){
await fetch(`/api/tasks/${id}`,{method:'DELETE'});
load();
}
load();
</script></body></html>
"""
@app.route("/")
def index():
return HTML
@app.route("/api/tasks", methods=["GET"])
def get_tasks():
with get_db() as conn:
rows = conn.execute("SELECT * FROM tasks ORDER BY id DESC").fetchall()
return jsonify([dict(r) for r in rows])
@app.route("/api/tasks", methods=["POST"])
def create_task():
data = request.get_json()
title = (data or {}).get("title", "").strip()
if not title:
abort(400, description="タスク名は必須です")
with get_db() as conn:
cur = conn.execute("INSERT INTO tasks (title) VALUES (?)", (title,))
task_id = cur.lastrowid
conn.commit()
logger.info(f"タスク追加: {title}")
return jsonify({"id": task_id, "title": title, "done": 0}), 201
@app.route("/api/tasks/<int:task_id>", methods=["PUT"])
def toggle_task(task_id):
with get_db() as conn:
conn.execute("UPDATE tasks SET done = 1 - done WHERE id=?", (task_id,))
conn.commit()
logger.info(f"タスク更新: id={task_id}")
return jsonify({"status": "ok"})
@app.route("/api/tasks/<int:task_id>", methods=["DELETE"])
def delete_task(task_id):
with get_db() as conn:
conn.execute("DELETE FROM tasks WHERE id=?", (task_id,))
conn.commit()
logger.info(f"タスク削除: id={task_id}")
return "", 204
if __name__ == "__main__":
init_db()
app.run(debug=False, port=5000)
まとめ
全50問、お疲れ様でした。各問題には具体的な入出力条件と解答例を掲載しました。解答例はあくまで一例です。同じ出力が得られれば、別のアプローチでも問題ありません。
初級をマスターしたら中級へ、中級が完了したら上級にチャレンジしてみてください。特に問題50の総合プロジェクトは、これまでの知識を総動員する内容になっています。