Python / LESSON 12 / PY12

Python:モジュールとパッケージ

1学習の目的

2基礎解説

やりたいこと書き方呼び出し方
モジュール全体を使うimport mathmath.sqrt(16)
一部だけ取り込むfrom math import sqrtsqrt(16)
別名を付けるimport math as mm.pi
自作ファイルを使うimport utilsutils.with_tax(1000)
✅ 覚えるべき重要ポイント
  1. import math したら math.sqrt() のように「モジュール名.関数名」で呼ぶ。どこから来た関数か一目で分かるのが利点。
  2. from math import sqrt なら直接 sqrt() と書ける。ただし from math import *何が入ってくるか分からず名前が衝突するので使わない。
  3. 自作モジュールは同じフォルダに .py を置いて import ファイル名import utils と書き、.py は付けない
  4. if __name__ == "__main__": の中身は直接実行したときだけ動き、importされたときは動かない。動作確認用コードの置き場所。
  5. パッケージ=モジュールを入れたフォルダ。中に __init__.py を置き、from mypkg import tax のように読み込む。

現場使用例:標準ライブラリ(math / statistics / os / csv / datetime / json)、社内の共通処理を utils.py に切り出す、設定値を config.py に分離して環境ごとに差し替える。

import math
from statistics import mean

print(math.sqrt(16))       # 4.0
print(math.ceil(3.2))      # 4
print(mean([10, 20, 30]))  # 20

# 別名を付ける
import math as m
print(f"{m.pi:.2f}")       # 3.14

# 自作モジュール(同じフォルダに utils.py を置いた場合)
# import utils
# print(utils.with_tax(1000))

3基本ドリル(10問)

PY12-D01 math モジュールを使って 16 の平方根を出力せよ。 コーディング★☆☆無料
期待される結果

出力 == 4.0

ヒント

import math してから math.sqrt(16)。

模範解答
import math

print(math.sqrt(16))
解説

平方根の計算式を自分で書く必要はない。まず標準ライブラリに無いか探すのがPythonの作法。

PY12-D02 import math と書いた後、平方根を求める正しい書き方はどれか。
A. sqrt(16) B. math.sqrt(16) C. math(sqrt(16)) D. import.sqrt(16)
選択★☆☆無料
期待される結果

解答 == B

ヒント

import した場合、関数の前に何を付けるか。

模範解答
B
解説

import math だけでは sqrt() 単体は使えない。直接書きたければ from math import sqrt が必要。

PY12-D03 math から ceil だけを取り込み、3.2 を切り上げた値を出力せよ。 コーディング★☆☆無料
期待される結果

出力 == 4

ヒント

from math import ceil と書けば ceil(3.2) と直接呼べる。

模範解答
from math import ceil

print(ceil(3.2))
解説

ceil は切り上げ、floor は切り捨て。int() は小数を捨てるだけなので、負の数では floor と結果が変わる点に注意。

PY12-D04 statistics から mean(平均)を取り込むコードを完成させよ。 穴埋め★☆☆無料
コード
____ statistics import mean

print(mean([10, 20, 30]))
期待される結果

出力 == 20

ヒント

「〜から取り込む」を表すキーワード。

模範解答
from
解説

statistics には mean のほか median(中央値)、mode(最頻値)、stdev(標準偏差)がある。集計処理で自前計算する前に確認したい。

PY12-D05 同じフォルダにある utils.py を読み込むときの正しい書き方はどれか。
A. import utils.py B. import utils C. import "utils.py" D. from utils.py
選択★☆☆無料
期待される結果

解答 == B

ヒント

拡張子は書くのか、書かないのか。

模範解答
B
解説

.py は付けないのがルール。ファイル名がそのままモジュール名になるので、ファイル名にハイフンや日本語を使わないこと。

PY12-D06 math を m という別名で取り込み、円周率を小数2桁で出力せよ。 コーディング★★☆無料
期待される結果

出力 == 3.14

ヒント

import math as m。表示は f"{m.pi:.2f}"。

模範解答
import math as m

print(f"{m.pi:.2f}")
解説

別名は長いモジュール名を短くするために使う。実務では pandas を pd、numpy を np と書くのが世界共通の慣習。

PY12-D07 直接実行したときだけ動作確認が走るコードを完成させよ。 穴埋め★★☆無料
コード
def hello():
    return "こんにちは"

____ == "__main__":
    print(hello())
期待される結果

出力 == こんにちは

ヒント

特殊変数 __name__ を使った定型の1行。

模範解答
if __name__
解説

この1行はほぼ定型句として覚えてよい。アンダースコアは前後に2つずつで計4つ。

PY12-D08 if __name__ == "__main__": の中に書いた処理はどうなるか。
A. 常に実行される B. 直接実行したときだけ実行され、importされたときは実行されない C. importされたときだけ実行される D. 実行されない
選択★★☆無料
期待される結果

解答 == B

ヒント

モジュールとして読み込まれたときに動いてほしくない処理は何か。

模範解答
B
解説

これが無いと、import しただけでテスト用の print が全部走る。モジュールを作るときは必ず付ける。

PY12-D09 同じフォルダに calc.py を作り、2つの数を足す関数 add を書け。そのうえで import して add(3, 7) の結果を出力せよ。 コーディング★★☆無料
期待される結果

出力 == 10

ヒント

PY11で学んだファイル書き込みで calc.py を作る。書き終わってから import calc する。

模範解答
with open("calc.py", "w", encoding="utf-8") as f:
    f.write("def add(a, b):\n    return a + b\n")

import calc

print(calc.add(3, 7))
解説

モジュールの正体はただの .py ファイル。特別な仕組みではなく、同じフォルダに置いて名前で呼ぶだけ。

PY12-D10 statistics を使って [70, 85, 90, 85] の平均と最頻値を、この順に1行ずつ出力せよ。 コーディング★★☆無料
期待される結果

出力 == 82.5 / 85(2行)

ヒント

statistics.mean() と statistics.mode()。

模範解答
import statistics

scores = [70, 85, 90, 85]

print(statistics.mean(scores))
print(statistics.mode(scores))
解説

最頻値を自分で書くとPY07の辞書集計が必要になるが、mode() なら1行。車輪の再発明を避けるのが実務の生産性を決める。

4実践シナリオ(5問)

PY12-S01 【共通処理をモジュール化】utils.py を作り、税込計算 with_tax(price, rate=0.1) と送料判定 shipping_fee(price)(5,000円以上で0、未満で600)を定義せよ。import して [4800, 12000] の2件を「4,800円 → 税込5,280円 / 送料600円」の形式で出力すること。 コーディング★★☆無料
期待される結果

出力2行が完全一致

ヒント

モジュールの中身は行のリストを作って "\n".join(lines) で書き出すと読みやすい。書き終えてから import utils する。

模範解答
lines = [
    "def with_tax(price, rate=0.1):",
    "    return int(price * (1 + rate))",
    "",
    "",
    "def shipping_fee(price):",
    "    if price >= 5000:",
    "        return 0",
    "    return 600",
]

with open("utils.py", "w", encoding="utf-8") as f:
    f.write("\n".join(lines))

import utils

for p in [4800, 12000]:
    print(f"{p:,}円 → 税込{utils.with_tax(p):,}円 / 送料{utils.shipping_fee(p)}円")
解説

PY08で作った関数を別ファイルに移すだけでモジュールになる。こうしておけば他のスクリプトからも同じ計算を呼べる。

PY12-S02 【設定値の分離】config.py を作り、SHOP_NAME("ゼロカラショップ")、TAX_RATE(0.1)、FREE_SHIPPING(5000)を定義せよ。import して「ゼロカラショップ」「税率:10%」「送料無料ライン:5,000円」の3行を出力すること。 コーディング★★☆無料
期待される結果

出力3行が完全一致

ヒント

設定値は大文字で書くのが慣習。税率の表示は {x:.0%} でパーセント表記になる。

模範解答
lines = [
    'SHOP_NAME = "ゼロカラショップ"',
    "TAX_RATE = 0.1",
    "FREE_SHIPPING = 5000",
]

with open("config.py", "w", encoding="utf-8") as f:
    f.write("\n".join(lines))

import config

print(config.SHOP_NAME)
print(f"税率:{config.TAX_RATE:.0%}")
print(f"送料無料ライン:{config.FREE_SHIPPING:,}円")
解説

変わる値をコードから追い出すのが設定分離の目的。税率が変わっても config.py の1行を直すだけで、全スクリプトに反映される。

PY12-S03 【標準ライブラリの組み合わせ】scores = [72, 85, 91, 68] について、math と statistics を使って「平均:79.0」「中央値:78.5」「平均の切り上げ:79」の3行を出力せよ(平均は小数1桁表示)。 コーディング★★☆無料
期待される結果

出力3行が完全一致

ヒント

statistics.mean() と statistics.median()、切り上げは math.ceil()。平均は {x:.1f} で表示する。

模範解答
import math
import statistics

scores = [72, 85, 91, 68]

print(f"平均:{statistics.mean(scores):.1f}")
print(f"中央値:{statistics.median(scores)}")
print(f"平均の切り上げ:{math.ceil(statistics.mean(scores))}")
解説

import は1行に1つ、標準ライブラリを先に、アルファベット順に並べるのが読みやすい書き方(PEP8)。中央値は平均と違い外れ値に強い指標。

PY12-S04 【パッケージを作る】mypkg というフォルダを作り、中に空の __init__.py と、税込計算 with_tax(price, rate=0.1) を持つ tax.py を配置せよ。from mypkg import tax で読み込み、[1000, 5000] を「1,000円 → 1,100円」の形式で出力すること。 コーディング★★★無料
期待される結果

出力2行が完全一致

ヒント

フォルダ作成は os.makedirs("mypkg", exist_ok=True)。ファイルパスは "mypkg/tax.py" のように書く。__init__.py は中身が空でよい。

模範解答
import os

os.makedirs("mypkg", exist_ok=True)

with open("mypkg/__init__.py", "w", encoding="utf-8") as f:
    f.write("")

lines = [
    "def with_tax(price, rate=0.1):",
    "    return int(price * (1 + rate))",
]

with open("mypkg/tax.py", "w", encoding="utf-8") as f:
    f.write("\n".join(lines))

from mypkg import tax

for p in [1000, 5000]:
    print(f"{p:,}円 → {tax.with_tax(p):,}円")
解説

パッケージ=モジュールを入れたフォルダ。機能が増えてファイルが散らかってきたら、種類ごとにフォルダへまとめる。__init__.py は「このフォルダはパッケージです」という目印。

PY12-S05 【__name__ の動作を確認する】check.py を作り、n を2倍にする関数 double と、if __name__ == "__main__": の中にテスト用の print を書け。そのうえで import check し、「importしました」「テスト出力は実行されていません」「double(5) = 10」「check.__name__ = check」の4行を出力せよ。 コーディング★★★無料
期待される結果

出力4行が完全一致

ヒント

import しただけなら __name__ は "__main__" ではなくモジュール名("check")になるので、ガードの中は実行されない。

模範解答
lines = [
    "def double(n):",
    "    return n * 2",
    "",
    "",
    'if __name__ == "__main__":',
    '    print("これはテスト出力です")',
]

with open("check.py", "w", encoding="utf-8") as f:
    f.write("\n".join(lines))

import check

print("importしました")
print("テスト出力は実行されていません")
print(f"double(5) = {check.double(5)}")
print(f"check.__name__ = {check.__name__}")
解説

「これはテスト出力です」が表示されないことがこの問題の答え。__name__ には直接実行時は "__main__"、import時はモジュール名が入る。この違いがガードの正体。

5仕上げ課題

PY12-FINAL 【請求書スクリプトのモジュール分割】PY08で1ファイルに書いた請求書処理を、設定と計算処理に分割して作り直せ。

config.py を作る — SHOP_NAME = "ゼロカラ商店" / TAX_RATE = 0.1 / MEMBER_DISCOUNT = 0.1
billing.py を作る — 中で import config し、3つの関数を定義
 ・subtotal(price, qty) … 単価×数量
 ・apply_discount(amount, is_member) … 会員なら MEMBER_DISCOUNT ぶん引く(整数に切り捨て)
 ・with_tax(amount) … TAX_RATE ぶん加算(整数に切り捨て)
③ 本体で両方を import し、以下のデータで請求書を出力
items = [("ノートPC", 128000, 1), ("マウス", 3200, 2), ("USBメモリ", 1500, 3)] / is_member = True

出力仕様(9行):
=== ゼロカラ商店 請求書 ===
ノートPC:128,000円 × 1 = 128,000円
マウス:3,200円 × 2 = 6,400円
USBメモリ:1,500円 × 3 = 4,500円
---
小計:138,900円
会員割引後:125,010円
消費税込:137,511円
(税率10% / 会員割引10%)
期待される結果

出力9行が完全一致

ヒント

モジュールの中身は行のリストを "\n".join() で書き出す。billing.py の先頭で import config すると、billing の中から config.TAX_RATE を参照できる。本体側では import config と import billing の両方が必要。

模範解答
config_lines = [
    'SHOP_NAME = "ゼロカラ商店"',
    "TAX_RATE = 0.1",
    "MEMBER_DISCOUNT = 0.1",
]

with open("config.py", "w", encoding="utf-8") as f:
    f.write("\n".join(config_lines))

billing_lines = [
    "import config",
    "",
    "",
    "def subtotal(price, qty):",
    "    return price * qty",
    "",
    "",
    "def apply_discount(amount, is_member):",
    "    if is_member:",
    "        return int(amount * (1 - config.MEMBER_DISCOUNT))",
    "    return amount",
    "",
    "",
    "def with_tax(amount):",
    "    return int(amount * (1 + config.TAX_RATE))",
]

with open("billing.py", "w", encoding="utf-8") as f:
    f.write("\n".join(billing_lines))

import config
import billing

items = [("ノートPC", 128000, 1), ("マウス", 3200, 2), ("USBメモリ", 1500, 3)]
is_member = True

print(f"=== {config.SHOP_NAME} 請求書 ===")

total = 0
for name, price, qty in items:
    line = billing.subtotal(price, qty)
    total += line
    print(f"{name}:{price:,}円 × {qty} = {line:,}円")

discounted = billing.apply_discount(total, is_member)
taxed = billing.with_tax(discounted)

print("---")
print(f"小計:{total:,}円")
print(f"会員割引後:{discounted:,}円")
print(f"消費税込:{taxed:,}円")
print(f"(税率{config.TAX_RATE:.0%} / 会員割引{config.MEMBER_DISCOUNT:.0%})")
解説

PY08と出力は同じだが構造が違うのがこの課題の要点。税率変更は config.py の1行、計算ロジックの修正は billing.py だけ、表示の変更は本体だけ——直す場所が役割ごとに決まっている状態を作れた。これが「大きなプログラムを作る」ということで、ファイルが10個100個に増えても破綻しない設計の基礎になる。