まずは先ほどの例をそのままメインスクリプトとライブラリファイルに分割します。
まずライブラリを入れておくためのフォルダとして"a02_lib"を作成しました。 先ほど使った"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()
## empty
from a02_lib.mylib import * form = MyForm("Hello World!") form.run()
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つのファイルに分かれたことになります。 変更のポイントを順番に説明していきます。
新しく作成したライブラリファイルは"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"の他にも、Form
やSize
などもクラスの名前だけで呼べる事がわかります。
ただし開発の規模が大きくなってくるといろいろなライブラリを使うため、MyForm
だけを使いたいのに余計なものも読み込まれ、もし他の人がそのライブラリで違う"MyFormクラス"を定義して読み込んでいた場合は混乱を引き起す事になります。
できるだけ読み込むライブラリは少ない方がよく、その制御をする方法が__all__
変数です。
この変数はimport *
で読み込まれる際にアスタリスクに何が入るのか指定する事ができます。
次のようにファイルを作り直す事ができます。
... __all__ = ['MyForm'] ...
mylib.pyファイルに、この変更を加えた後でdir()を実行してみます。
>>> from a02_lib.mylib2 import * >>> dir() ['MyForm', '__builtins__', '__doc__', '__name__']
引き続きライブラリの内部ではForm
やSize
はクラス名だけで利用できますが、ライブラリをimportして利用する側で はMyForm
クラスの1つだけがみえるようになりました。
空のファイルで作成した__init__.pyファイルの役割は、先ほどの__all__
行の管理が中心です。
ライブラリを開発していくと、フォルダの中にいろいろなファイルができていきます。 そのライブラリ本来の動きをサポートするためのユーティリティ的なクラスも多数できるでしょう。
またライブラリが提供するクラスの数が増えていった時に、form a02_lib.mylib
のようにフォルダ名とファイル名を組み合せるのはファイルの数だけ行数が増えるので非効率です。
またファイル名を覚えておくことも、難しくなるでしょう。
そこでフォルダ名だけを使ってimportできるようにする仕組みの土台を提供するのが__init__.pyファイルです。
先ほど作成したコメントだけの__init__.pyファイルを変更し、処理本体の一行目を__init__.pyに合うように変更します。
## empty
from a02_lib.mylib import * form = MyForm("Hello World!") form.run()
__all__ = ["MyForm"] from a02_lib.mylib import *
from a02_lib import * form = MyForm("Hello World!") form.run()
本体スクリプトの変更部分は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
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.