はじめに
pythonでプログラムを作りはじめたとき、サブルーチンは、どう書くのだろうという疑問を持ちました。
過去の話になりますが、BASIC言語ではプログラムを作るとき、何度も使う部分は一つにまとめて、gosub文で呼び出していたので、pythonにもあるだろうと思っていましたが、そのような文はありませんでした。
pythonのプログラムを学んでいくと、def文で関数をつくって、それを呼び出せば、サブルーチンの代わりになることが分かってきました。さらに、別ファイルに関数をまとめて作っておくと、他のプログラムで利用できるようになり、便利に使えるということもわかってきました。
プログラマーには当たり前の話かと思いますが、これからpythonを始める人に少しでも役立てていただけるように、例を挙げて書いておこうと思います。
def文の例
(例) 画像読み込み関数の作成
例えば、openCVを使って画像の編集をしたいが、画像ファイルのパスに日本語が入っていてエラーが出るため、つぎのようなプログラムを作ったとします。
import cv2
from PIL import Image
import numpy as np
file=r'C:\Users\heroshi\OneDrive\画像\abc.jpg'
pil_img=Image.open(file)
np_img=np.array(pil_img)
cv_img=cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)
PIL(pillow)でファイルを読み込み、numpyアレイに変換し、さらにカラー順を変換して、ようやくopenCVで画像を編集できるようになるのですが、画像を読み込むたびに、この3行を書くのは面倒ですし、分かりにくくなります。そこで、def文で関数を1つ用意し、その中に3行を入れておきます。
import cv2
from PIL import Image
import numpy as np
def load_img(file):
pil_img=Image.open(file)
np_img=np.array(pil_img)
cv_img=cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)
return cv_img
file=r'C:\Users\heroshi\OneDrive\画像\abc.jpg'
cv_img=load_img(file) #関数の呼び出し gosub文のようなもの
上のプログラムはdef文で「load_img」という名前をつけた関数を定義しています。プログラムは長くなっていますが、BASIC言語のサブルーチンのように「load_img」を何度も使うときに便利になります。
例えば、画像を2つ読み込んで、画像を足しあわせる場合は次のように書けます。
import cv2
from PIL import Image
import numpy as np
def load_img(file):
pil_img=Image.open(file)
np_img=np.array(pil_img)
cv_img=cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)
return cv_img
file_1=r'C:\Users\heroshi\OneDrive\画像\abc.jpg'
file_2=r'C:\Users\heroshi\OneDrive\画像\def.jpg'
cv_img_1=load_img(file_1) #関数の呼び出し gosub文のようなもの
cv_img_2=load_img(file_2)
mix_img= cv2.addWeighted(src1=cv_img_1,alpha=0.5,src2=cv_img_2,beta=0.5,gamma=0)
(例) 画像の表示関数の作成
画像を表示する際、openCVのcv2.imshowを使って描くよりも、matplotlibのplt.showを使ったほうが拡大縮小も簡単に操作できるので、次のようなプログラムを作って描画しています。
import matplotlib.pyplot as plt
plt_mix_img=cv2.cvtColor(mix_img, cv2.COLOR_BGR2RGB) # BGRからRGBへ変換して表示
plt.imshow(plt_mix_img)
plt.axis('off') # 軸を非表示にする
plt.show()
こちらも表示させるのに何度も同じ文(4行)を書くのが面倒なので、次のようにdef文で関数を定義します。
import matplotlib.pyplot as plt
def draw_img(image):
plt_mix_img=cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # BGRからRGBへ変換して表示
plt.imshow(plt_mix_img)
plt.axis('off') # 軸を非表示にする
plt.show()
draw_img(mix_img) #関数の呼び出し gosub文のようなもの
関数だけを別ファイルへ
上の例では、ファイルの読み込みと画像の描画の関数を作りました。その関数だけを別のファイルに入れて、ファイル名は、dif_list.pyとします。
import cv2
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
def load_img(file):
pil_img=Image.open(file)
np_img=np.array(pil_img)
cv_img=cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)
return cv_img
def draw_img(image):
plt_mix_img=cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # BGRからRGBへ変換して表示
plt.imshow(plt_mix_img)
plt.axis('off') # 軸を非表示にする
plt.show()
次に実行するファイルを作ります。def_listから関数をインポートすることで、実行ファイルの中身は非常にすっきりします。※実行ファイルと関数のファイルは同じフォルダに入れています。
import cv2
from def_list import * #ここでdef_listのファイルから関数をインポートします。*は、すべてという意味です。
file_1=r'C:\Users\heroshi\OneDrive\画像\abc.jpg'
file_2=r'C:\Users\heroshi\OneDrive\画像\def.jpg'
cv_img_1=load_img(file_1)
cv_img_2=load_img(file_2)
mix_img= cv2.addWeighted(src1=cv_img_1,alpha=0.5,src2=cv_img_2,beta=0.5,gamma=0)
draw_img(mix_img)
関数にわかりやすい名前をつけることで、使いやすいものになり、別の実行プログラムでも、関数をインポートすることで同様に使えるようになります。
関数の修正や追加時の確認
関数の修正や追加した際に、きちんと動くかを確認したい場合があると思います。こんなとき、関数のファイルの最後に、if _ _ name _ _ =="_ _ main _ _" 文を入れておけば、関数ファイルのみで実行して確認できるようになるので、こちらもお勧めです。
import cv2
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
def load_img(file):
pil_img=Image.open(file)
np_img=np.array(pil_img)
cv_img=cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)
return cv_img
def draw_img(image):
plt_mix_img=cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # BGRからRGBへ変換して表示
plt.imshow(plt_mix_img)
plt.axis('off') # 軸を非表示にする
plt.show()
if __name__=="__main__":
file=r'C:\Users\heroshi\OneDrive\画像\abc.jpg'
cv_img=load_img(file)
deaw_img(cv_img)
さいごに
最初はBASIC言語のサブルーチンってpythonでどう書くんだろうと思っていましたが、pythonを学んでいくうちに、def文でできることを知り、関数を別ファイルとして用意しておけば、インポートするだけで、他のプログラムでも使えるようになるということを知りました。プログラミングの進化を感じた次第です。