Python初心者がScikit-imageの例題を自分用に使うためのヒント7　モジュールの作り方


引き続きPython初心者向けの内容を書いてみます。

 Pythonの用途が拡大した理由の１つは、その充実したライブラリの存在です。
GUIの利用やネットワークアプリの記述がこんなに簡単な理由は明らかに、Pythonのライブラリの充実が充実しているからです。

 今回は、既に書いてあるスクリプトをモジュールとして使えるように再利用性を向上させるためのPythonの書き方を説明します。

###**お約束事の少ない言語**
Pythonはプログラムを書き始めるためのお約束ごとが、とても少ない言語です。

```
print "Hello World"
```

とだけ書いても立派なPythonプログラムです。C/C++言語の場合にはmain関数を書く必要があります。Javaの場合だったら、classを作って、public static void main(String[] args)というメソッドを定義する必要があります。そのようなお約束ごとは、その言語を習得する上で避けて通れないものです。
Python言語は、そのようなお約束が少ないまま、使い始めることができます。

```
a = 1
b = 2
print a+b
```

のように記述できることは、その約束事の少なさによるものです。

###**すべてのオブジェクトはprintできる**
python言語から、ユーザーへのお約束事は、
ほとんどのオブジェクトは
print そのオブジェクトの識別子
でprintできるということです。

数値、文字列、リスト、タプル、辞書、numpy.array型、クラスのインスタンス、python言語で扱うオブジェクトをprintできるという点です。

このことは、Python言語の利用者にC言語のprintf("%d",  int型変数), printf("%f", double型変数) などという使い分けを強要しないし、間違った使い方を生じる余地もなくしています。
どんなに複雑なデータ形式であってもprintできることは、使い方がわからない関数の戻り値がどんな複雑なデータ形式になっていてもprintすることで理解することを可能にしてくれています。

注：Pythonのインタプリタ上では

```
>>> a+b
3
>>> 
```

とするだけでprintなしにオブジェクトを表示してくれます。

注：printはprint文であって、関数ではない特別なものになっています。またprint()関数もあって、同じような使い方ができます。ですから、ご覧になるpythonのソースコードでは、Python2.x系統ではprint文を用いている傾向が多く、Python3.x系統ではprint()関数を使っている傾向が多いと思います。
　

####**Pythonユーザーに求めるお約束事**
Python言語はif文、while文、for文などの制御構文の範囲としてインデントを用いているという点です。
このため、コピーアンドペーストしたスクリプトで、インデントが元々のスクリプトと異なっていると動作が違ってしまうという点です。

なれるまでは、尻切れトンボになっているようで、「残りはどこにいったの？」と戸惑うことがありますが、Python言語の有用な例題を自分のものにしていくうちに、自然に慣れていくことができると思います。


###**import しよう**
Python言語ではimport　モジュール名すると、そのモジュールをモジュール名.関数名で、モジュール内の関数にアクセスできます。

import cv2
img = cv2.imread("lena.jpg")
とできます。

自分の書いた
myModule.py
にある関数myfunc()
があるとき、
import myModule
myModule.myfunc()
で自作ライブラリを利用することができます。


```.py:modNcut.py
from skimage import data, io, segmentation, color
from skimage.future import graph
from matplotlib import pyplot as plt

def plotNcut(img):
    labels1 = segmentation.slic(img, compactness=30, n_segments=400)
    out1 = color.label2rgb(labels1, img, kind='avg')
    
    g = graph.rag_mean_color(img, labels1, mode='similarity')
    labels2 = graph.cut_normalized(labels1, g)
    out2 = color.label2rgb(labels2, img, kind='avg')
    
    plt.figure(1)
    io.imshow(out1)
    plt.figure(2)
    io.imshow(out2)
    io.show()

```

という関数を作ったあとには、
この関数があるディレクトリで(あるいは、このモジュールにPYTHONPATHが通っていれば)

```
import modNcut
import cv2
img = cv2.irmread("lena.jpg")
modNcut.plotNcut(img)
```

として利用できます。
自作モジュールを使う上で、コンパイルとか登録とか特別な作業なしに利用できることが、とても簡単に開発を進めることを可能にしてくれています。
関数をどのような仕様で作るか、とくにその引数と戻り値をどのようにしたら使いやすいか。実際に書いてみて使いながら確かめていくのがとても容易になります。

python言語のお約束事の少なさは、インストールするためのモジュールの書き方にも現れています。
###**モジュールを書く際のほとんど唯一の約束事**
・モジュールとして呼び込んだときには実行させたくないコード（＝メインのプログラムとして選択したときだけ実行したいコード）は、```if __name__ == "__main__":```　のif文の中に書く。

　C/C++言語のmain関数に相当する部分をPython言語では、次のif文の部分に記載します。```if __name__ == "__main__":``` で始まるif文の範囲は、そのスクリプトファイルが、mainとして実行されたときにだけ実行される部分となります。　import文でそのスクリプトファイルが呼び込まれたときには、```if __name__ == "__main__":``` で始まるif文の範囲は　実行されません。

```if __name__ == "__main__":```

[__main__ — トップレベルのスクリプト環境](http://docs.python.jp/2/library/__main__.html)

Python チュートリアル [モジュール](http://docs.python.jp/2.7/tutorial/modules.html)


###**Pythonモジュールの実装**
python言語のモジュールには、実はいろいろな実装があります。python言語で書かれたモジュール。C/C++で書かれた書かれたモジュール。Cython言語を元にして書かれたモジュール。全ては
import モジュール名
でimportできます。help(モジュール名.関数名)で関数の説明を得られることなど、すべて共通です。
Python(x,y)をインストールしてある環境ならば、
スタートメニューから
[Python(x,y)][Documentation]
[python documentation server]で[open browser]で「Python: Index of Modules」
のwebサーバーをローカルに立ち上げることができます。
そのブラウザ画面で利用できるライブラリをたどって関数やクラスの説明を見つけることができることなど、pythonのモジュール全て共通です。


追記
参考になるURL
[PyCon JP 2012 Pythonプログラミングハンズオン(初級者向け) documentation スクリプトファイルとモジュール化](http://pyconjp2012-python-for-beginners.readthedocs.org/en/latest/script_module.html)
[1.2.5. コードの再利用: スクリプトとモジュール](http://www.turbare.net/transl/scipy-lecture-notes/intro/language/reusing_code.html)




[ヒント８処理時間の計測とプロファイラ](http://qiita.com/nonbiri15/items/fa9036f612183fb3d242)