IronPythonを使ってみる

スクリプトの分割 〜本体とライブラリ〜

まずは先ほどの例をそのままメインスクリプトとライブラリファイルに分割します。

1. MyFormライブラリの作成

まずライブラリを入れておくためのフォルダとして"a02_lib"を作成しました。 先ほど使った"a01_formclass.ipy"ファイルを元に本体とライブラリのファイルに分けていきます。

変更前:a01_formclass.ipyファイル

import clr
clr.AddReferenceByPartialName("System.Windows.Forms")
clr.AddReferenceByPartialName("System.Drawing")
import System
from System.Windows.Forms import Form
from System.Drawing import Size

class MyForm(Form):
  def __init__(self):
    self.Size = Size(300,200)
    self.Text = "Hello World!"
    pass

  def run(self):
    System.Windows.Forms.Application.Run(self)
  pass

## main ##
form = MyForm()
form.run()

変更後:空のa02_lib\__init__.pyファイル

## empty

変更後:a02_formclass.ipyファイル

from a02_lib.mylib import *

form = MyForm("Hello World!")
form.run()

変更後:a02_lib\mylib.pyファイル

import clr
clr.AddReferenceByPartialName("System.Windows.Forms")
clr.AddReferenceByPartialName("System.Drawing")
import System
from System.Windows.Forms import Form
 from System.Drawing import Size

class MyForm(Form):
  def __init__(self, title):
    self.Size = Size(300,200)
    self.Text = title
    pass

  def run(self):
    System.Windows.Forms.Application.Run(self)
  pass

変更前は一つのファイルだったのに、3つのファイルが作成されました。 最後のファイルは空なので、実質的に2つのファイルに分かれたことになります。 変更のポイントを順番に説明していきます。

2. 本体:from a02_lib.mylib import *文

新しく作成したライブラリファイルは"a02_lib\mylib.py"ですが、これを呼び出すためにfrom a02_lib.mylib import *文を使っています。

これを実行した後は、a02_lib.mylib.MyFormではなくMyFormのようにクラスの名前でアクセスできるようになります。 どのクラスが名前で呼べるのか、その様子はdir()コマンドで確認する事ができます。

> ..\ipy.exe
>>> from a02_lib.mylib import *
>>> dir()
['Form', 'MyForm', 'Size', 'System', '__builtins__', '__doc__', '__name__', 'clr']  

"MyForm"の他にも、FormSizeなどもクラスの名前だけで呼べる事がわかります。

ただし開発の規模が大きくなってくるといろいろなライブラリを使うため、MyFormだけを使いたいのに余計なものも読み込まれ、もし他の人がそのライブラリで違う"MyFormクラス"を定義して読み込んでいた場合は混乱を引き起す事になります。

できるだけ読み込むライブラリは少ない方がよく、その制御をする方法が__all__変数です。

3. __all__変数

この変数はimport *で読み込まれる際にアスタリスクに何が入るのか指定する事ができます。 次のようにファイルを作り直す事ができます。

__all__行の追加

...
 __all__ = ['MyForm']
...

mylib.pyファイルに、この変更を加えた後でdir()を実行してみます。

>>> from a02_lib.mylib2 import *
>>> dir()
['MyForm', '__builtins__', '__doc__', '__name__']  

引き続きライブラリの内部ではFormSizeはクラス名だけで利用できますが、ライブラリをimportして利用する側で はMyFormクラスの1つだけがみえるようになりました。

4. __init__.pyファイルの役割

空のファイルで作成した__init__.pyファイルの役割は、先ほどの__all__行の管理が中心です。

ライブラリを開発していくと、フォルダの中にいろいろなファイルができていきます。 そのライブラリ本来の動きをサポートするためのユーティリティ的なクラスも多数できるでしょう。

またライブラリが提供するクラスの数が増えていった時に、form a02_lib.mylibのようにフォルダ名とファイル名を組み合せるのはファイルの数だけ行数が増えるので非効率です。 またファイル名を覚えておくことも、難しくなるでしょう。

そこでフォルダ名だけを使ってimportできるようにする仕組みの土台を提供するのが__init__.pyファイルです。

4-1. __init__.pyファイルを利用したスクリプトとライブラリ

先ほど作成したコメントだけの__init__.pyファイルを変更し、処理本体の一行目を__init__.pyに合うように変更します。

オリジナル:空のa02_lib\__init__.pyファイル

## empty

オリジナル:a02_formclass.ipyファイル

from a02_lib.mylib import *

form = MyForm("Hello World!")
form.run()

変更後:a02_lib\__init__.pyファイル

__all__ = ["MyForm"]
from a02_lib.mylib import *

変更後:02_formclass.ipyファイル

from a02_lib import *

form = MyForm("Hello World!")
form.run()

4-2. 変更のポイント

本体スクリプトの変更部分はfrom a02_lib import *の部分だけです。 この文にはライブラリファイル'mylib.py'に関連する名前は一切でてきません。 そして結果としてMyFormクラスだけに名前でアクセスできるようになります。

将来、mylib.pyファイルを複数のファイルに分割しても、__init__.pyファイルの変更だけが必要になります。

__all__行は無理に使う必要はなく、代替手段がある方法です。実際に標準ライブラリの多くで使われていません。 しかし、それは__all__行が直接使えるほど単純な場合が少ないからのようで、ほとんどは__init__.pyファイルでクラス名のロードが制御されています。 ライブラリを眺めてクラスを使おうとした時に、本体をどうやって呼び出したらよいのか分からなくなるところなので、__init__.pyファイルには慣れておいた方が良さそうです。


Created: 2010-03-13, Last modified: 2010-03-19

2009,2010 © Yasuhiro ABE <yasu@yasundial.org>

Valid XHTML + RDFa RDFa it (RDF/XML)!

正当なCSSです!

Creative Commons License www.yasundial.org by Yasuhiro ABE is licensed under a Creative Commons Attribution 2.1 Japan License. Permissions beyond the scope of this license may be available at http://www.yasundial.org/info/license.html.