CHAPTER 4 ・ コードを整理して育てる / Lesson 14

ファイルを分けて、import で使う

関数を別のファイルに移して、必要な場所から呼び出す。標準ライブラリの地図も持ち帰ります。

目安 20分 ・ インストール不要

このレッスンが終わったら

「関数を別ファイル(モジュール)に分けて、import で使える。標準ライブラリは、まず探してから自作する」と言える。

STEP 1

こんな場面、ありませんか?

便利な関数を作ると、別のスクリプトでも使いたくなります。そこで、関数をコピーして貼り付けることが、よく起きます。たとえば、請求書を作るスクリプトと、見積書を作るスクリプトの両方に、同じ「税込にする関数」を貼ったとします。

同じ関数を、2つのスクリプトにコピーするとコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

片方だけ直して、もう片方を直し忘れると、同じ10,000円なのに、書類によって金額が違う事故になります。コピーが増えるほど、直し忘れも増えます。関数を1つのファイルにまとめて置き、必要な場所から呼び出す。これが、この回の主役、モジュールです。

STEP 2

ファイルに分けて、import で使う

関数を入れたファイル(tools.py)を作り、それを使う側から import tools と書きます。ここでは学習用に、tools.py をプログラムの中から書き出してから使います。自分のパソコンでは、エディタで tools.py を作って保存するのと同じことです。

tools.py を作って、import して使うコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

11000 と 1620 が表示されましたか。tools.with_tax(...) は、「tools の中の with_tax を使う」という意味です。これで、税込にする関数は tools.py の1か所だけになりました。直すときも、その1か所です。(sys.modules.pop の1行は、この画面で何度実行しても、書き直した tools.py が読み込まれるようにするためのものです。自分のパソコンでは必要ありません)

STEP 3

仕組みを読む

  1. tools.py関数を置いておくファイル
  2. import tools使う側が「借りる」と宣言
  3. tools.with_tax()借りた関数を呼ぶ
部品は1つのファイルに置き、使う側が必要なときに借りてくる。

import の書き方は3通りあります。どれも、同じ関数を使えます。

from tools import with_tax の部品
fromどのファイルから?
toolsモジュールの名前(tools.py の、.py を除いたもの)
import借りてくる
with_tax借りたい関数
3通りの import を、日本語にしてみる
import toolstools を丸ごと借りる。使うときは tools.with_tax(...) と、頭に名前を付ける
from tools import with_taxwith_tax だけを借りる。使うときは with_tax(...) と、そのまま書ける
import tools as ttools に t という短い別名を付けて借りる。t.with_tax(...) と書く
STEP 4

変えて、試す

① 3通りの import を、動かして比べる。
3通りの importコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

② 名前を打ち間違える。 tools.py があるつもりで、名前を間違えて import すると、見つからずにエラーになります。

わざと間違える:モジュール名の打ち間違いコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

ModuleNotFoundError: No module named 'toools' と出ます。「toools という名前のモジュールは見つかりません」という意味です。名前の打ち間違いのほか、ファイルが別のフォルダにあるときにも出ます。ファイルの名前と、置き場所を確かめます。from tools import with_taxx のように関数名を間違えたときは、ImportError: cannot import name 'with_taxx' と出ます。

③ if __name__ == "__main__": の意味。 モジュールの下に、試し用の print を書いておくと、import したときにも動いてしまいます。そこで、次の1行を使います。

import したときは動かない部分コードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

Python は、ファイルを直接実行したときは __name__ を "__main__" にし、import で読み込まれたときはファイルの名前(ここでは tools)にします。そのため if __name__ == "__main__": の中は、import されたときには動きません。この書き方は、AIが書くスクリプトの最後に、よく出てきます。

④ 前の回の関数を、モジュールにして使う。 Lesson 13 の load_rows と month_summary を、sales_tools.py にまとめて使います。

sales_tools.py を作って、集計するサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

使う側は、from sales_tools import ... の1行と、3行ほどで済みます。月ごとの集計を使うスクリプトが何本あっても、直すのは sales_tools.py だけです。

⑤ まず、標準ライブラリを探す。 平均・中央値・切り上げ・件数のカウントなど、「あるだろう」と思う処理は、たいてい標準ライブラリに入っています。自分で書く前に探すと、短く、間違いも少なくなります。

標準ライブラリを使ってみるコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます
モジュールできることこの講座
datetime日付・時間の計算Lesson 03
decimal誤差のないお金の計算Lesson 04
collections件数のカウント、既定値つき辞書Lesson 06
pathlibファイル・フォルダの扱いLesson 18
csv / jsonCSV・JSON の読み書きLesson 19
re文字のパターン検索Lesson 20
itertools繰り返しの便利な部品Lesson 21
statistics / math / random平均・中央値、切り上げ、乱数(実行のたびに結果が変わる)この回
STEP 5

自分で書く

お題① 金額を「万円」に直す関数 to_man(amount) を、money.py に書き出して、import して使ってください。to_man は、金額を 10000 で割った整数部分(//)を返します。to_man(320000) を表示します。

お題①:モジュールを作って呼ぶコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

source の中に def to_man(amount): と、return amount // 10000 を書きます。そのあと from money import to_man として、print(to_man(320000)) を実行します。

答えの例を見る
import sys

source = '''
def to_man(amount):
  return amount // 10000
'''

with open("money.py", "w", encoding="utf-8") as f:
  f.write(source)

sys.modules.pop("money", None)
from money import to_man

print(to_man(320000))

お題② 標準ライブラリの statistics を使って、次の売上の中央値を表示してください。(statistics.median は、数字のリストを、小さい順に並べたときの真ん中の値を返します)

お題②:標準ライブラリを使うコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

import statistics のあと、print(statistics.median(sales)) と書きます。from statistics import median でもかまいません。

答えの例を見る
import statistics

sales = [320000, 150000, 410000, 180000, 380000]
print(statistics.median(sales))
STEP 6

仕事ならどう使う?

理解チェックtools.py に with_tax という関数があります。tools.with_tax(100) の形ではなく、with_tax(100) とそのまま書いて使うには、どう import しますか?

理解チェックモジュールの中に if __name__ == "__main__": と書いたブロックがあります。このブロックが動くのは、いつでしょう?