今までの回で,Pythonの基本的な文法やデータ型,制御構文,関数,クラスについて説明しました. 今回はそれらを用いてプログラムを作成する上で役に立つ情報について説明していきます. 具体的にはモジュール,外部ライブラリ,そしてより良いコードを書くためのコツについて説明します.
困難は分割せよ
大きなものを一度に作ろうとするのは難しいことが多いです. そこで,作りたいものを小さな部品に分割して,それらを組み合わせて作ることが多いです. 例えばパソコンは,CPU,メモリ,ハードディスク,ディスプレイ,キーボード,マウスなどの部品を組み合わせて作られています. このようにモジュールに分けることで,作るものが小さくなりそれぞれの部品を作るのは見通しが立ちやすくなります. また,使う部品を入れ替えることなどもできるため,改良・拡張などもしやすくなります. (メモリを交換して16GBから32GBに変更するみたいに)
ソフトウェアも同じで,大きなものを一度に作るのは難しいので,小さな部品に分割して作ることが多いです. (もし数千行のコードを一つのファイルに書いたら...修正する場所を探すだけでも苦労しそうです) この小さな部品のことをモジュールと呼びます. モジュールは一つのファイルだったり,複数のファイルを集めたパッケージだったりします.
外部のファイルに書いたものを使うには,import
文を使います.
例えば cat.py
というファイルに以下のようなコードを書いたとします.
class Cat():
def __init__(self, name):
self.name = name
def meow(self):
print("にゃーん")
def get_name(self):
return self.name
このファイルの中で定義されているクラスCat
を別のファイルで使いたいとします.
そのときには,以下のようにimport
文を使います.
import cat
tama = cat.Cat("タマ")
tama.meow()
import
文を使うと,cat.py
の中で定義されているクラスや関数を使うことができます.
import
文を使うときには,import
したファイル名の後に.
をつけて,その後にimport
したいクラス名や関数名を書きます.
cat.Cat
は,cat.py
の中で定義されているCat
クラスを使うという意味です.
import cat as neko
のように,別名でimport
することもできます.
その場合は,cat.Cat
の代わりにneko.Cat
と書くことになります.
import cat as neko
tama = neko.Cat("タマ")
tama.meow()
cat.py
の中には,Cat
クラス以外にも,BlackCat
クラスが定義されているとします.
このとき,BlackCat
クラスは使わないので,import
しないようにしたいとします.
このようなときは,from cat import Cat
のように書きます.
from cat import Cat
tama = Cat("タマ")
tama.meow()
from cat import Cat
と書くと,cat.py
の中で定義されているCat
クラスだけをimport
します.
このように書いたときは,cat.Cat
の代わりにCat
と書きます.
複数のファイルをまとめて,一つのパッケージとして扱うこともできます.
cat.py
の他にdog.py
というファイルを作って,これらをまとめてanimal
パッケージとしてまとめたいとします.
そのときは,animal
というフォルダを作り,その中にcat.py
とdog.py
を入れます.
animal
をパッケージとしてPythonに認識させるには,animal
フォルダの中に__init__.py
というファイルを作る必要があります.
中身は空で大丈夫です.
animal
├── __init__.py
├── cat.py
└── dog.py
animalフォルダと同じ階層に,app.py
というフォルダを作り,animalパッケージの中のcat.py
とdog.py
を使ってみます.
├── animal
│ ├── __init__.py
│ ├── cat.py
│ └── dog.py
└── app.py
from animal import dog, cat
tama = cat.Cat("タマ")
tama.meow()
poti = dog.Dog("ポチ")
poti.woof()
from animal import dog, cat
と書くと,animal
パッケージの中のdog.py
とcat.py
をimport
します.
このように複数のファイルをまとめてパッケージとして扱うことで,より大きなプログラムを作ることができるようになります.
モジュールがどのように使われるのか想像がつかないと思うので,実際にモジュールを使った例を紹介します. ここでは,DjangoというWebアプリケーションフレームワークで作られたWebアプリを例にします. 僕のサイト(https://crashrt.work)は,Djangoを使って作りました.
DjangoでWebアプリを作ると,このようなディレクトリ構造になることが多いです. ここでは,トップページとプロジェクトを説明するページがある場合について考えてみます.
├── manage.py
├── top
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── projects
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
└── mysite
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
Webサービス勉強会ではないので詳しくは見ませんが, トップページとプロジェクトページでは全然役割が違う場合などは,このようにモジュールに分けておくと便利です. 各ページの中でも,
models.py
では,データベース関連の処理views.py
では,ページの表示に必要な処理urls.py
では,どのURLにアクセスしたときに行う処理を指定
などのように,役割ごとにファイルを分けておくと,プログラムが見やすくなります.
Pythonでは,様々なモジュールが公開されています.
Pythonに標準でインストールされているものは,標準ライブラリと呼ばれ,ただimport
するだけで使うことができます.
例えば,math
というモジュールを使うと,数学関連の処理を簡単に行うことができます.
import math
print(math.sqrt(2)) # √2
print(math.exp(2)) # e^2
print(math.log(2)) # log2
print(math.sin(math.pi / 6)) # sin(π/6)
標準でインストールされているモジュール以外にも様々なモジュールがあり,
pip
コマンドなどで簡単にインストールすることができます.
例えば,numpy
というモジュールを使う場合は,pip install numpy
とコマンドを打つとインストールできます.
numpyは,数値計算を行うときに便利なモジュールです.
行列の積を計算してみます.
import numpy as np
A = np.matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
B = np.matrix([[1, 1, 1], [0, 1, 1], [0, 0, 1]])
print(A)
print(B)
AB = np.dot(A, B)
print(AB)
numpyの他に,matplotlib, sympy, pandas などは便利なので特に理系の人は調べて見ても良いかもしれません. レポートを書くときとかに役立つと思います. さっき例に出したDjangoも,外部ライブラリの一つでWebアプリを作るときに使うと便利です. 他にもたくさんあるので,何か作りたいものがある場合は何か良いライブラリが無いか調べてみると良いと思います.
最後に,より読みやすいコードを書くためのコツをいくつか紹介します. コードを書くときには,自分以外の人が見ても分かりやすいように書くようにしましょう. 仮に自分しか見ないコードでも,分かりやすくすることは大切です. 半年後に修正したくなっても何も覚えていないことが多くて,読みにくいコードだと何してるのか分からず修正が難しくなります. 読みやすいコードを書きましょう!
ここで紹介したものの他にも,読みやすいコードを書くためのコツはたくさんあります. 興味がある人はオライリーの『リーダブルコード』という本を読んでみてください. 京大のルネにも置いてあります. 200ページくらいの読みやすい本で,コードを書くときの参考になると思います.
変数や関数などに名前をつけるときは,分かりやすい名前をつけるようにしましょう.
面倒くさいからといって適当にhoge
とかつけるのは避けた方が良いです.
例えば三角形の面積を計算する関数なら,triangle_area
とかつけると良いです.
def hoge(a, b):
tmp = a * b / 2
return tmp
よりも
def triangle_area(width, height):
area = width * height / 2
return area
の方が後で見たときに分かりやすいと思います.
似たような処理をするものがある時は,名前の違いで区別すると良いです. 名前だけで説明しきれない場合は,コメントを書きましょう.
def calc_area(width, height):
area = width * height
return area
def calc_area2(width, height):
area = width * height / 2
return area
よりは
def calc_area_rectangle(width, height):
area = width * height
return area
def calc_area_triangle(width, height):
area = width * height / 2
return area
のほうが,二つの関数の違いが名前だけで分かるので良いです. 今は関数の中身が簡単なので良いですが,これが複雑な処理になってくると地獄です. 名前をつけるときは,分かりやすい名前をつけるようにしましょう.
関数には,関数の説明を書くことができます.
関数の説明は,関数の定義の直下"""
で囲んだ部分に書きます.
関数が何を行うのか,引数は何か,戻り値は何か,などを書いておくと良いでしょう.
def triangle_area(width, height):
"""
三角形の面積を計算する
引数
width:float 底辺の長さ
height:float 高さ
戻り値
area:float 三角形の面積
"""
area = width * height / 2
return area
VSCodeとかで関数を使おうとしたときにdocstringの内容を表示してくれるので便利です. どんどん活用していきましょう.
Pythonは動的型付け言語なので,変数の型は勝手に変わって行きます. しかし,コードを書いていく上で想定している型などはあると思います. それらをヒントとして書いておくと,後で見て分かりやすいし,VSCodeなどがヒントを表示してくれたりするので便利です.
def triangle_area(width:float, height:float) -> float:
"""
三角形の面積を計算する
引数
width:float 底辺の長さ
height:float 高さ
戻り値
area:float 三角形の面積
"""
area = width * height / 2
return area
w: float = 10.0
h: float = 16.0
area: float = triangle_area(w, h)
変数・引数は名前の後ろに :
をつけて,
関数の戻り値は,関数名の後ろに ->
をつけて型を書きます.
今回は,モジュールとライブラリ,そしてコードを読みやすくするためのコツを紹介しました. 管理しやすく,読みやすいコードを書いて,良きプログラミングライフを送ってください!
- 困難は分割せよ
- 大きいものを作るときは,いくつかのモジュールに分けながら作る - いくつかのファイルに分けたり,ファイルが多くなったらパッケージにまとめたり
- 標準ライブラリ・外部ライブラリは便利
- コードを読みやすくしよう
- 分かりやすい名前をつける
- docstringを書く
- 型ヒントを書く
プログラミングに関する講座は今回で終わりですが,追加で2回,KMCで生活していく上で知っていると便利なことについて解説します. 次回の内容はGitという,バージョン管理や共同作業をするためのツールについて,見ていきます.