Python – モジュール その2
2009年5月22日 12:27 AM by Abalone




モジュールの続き。
モジュールで定義されている変数とかを使用する方法はもう一つある。
その1で勉強したimport文と似ているのだが、from〜import文がそれ。
import文もfrom文も、どちらも他のモジュールで定義された要素を使用できるようになるのだが、一番の違いは、import文を使用したモジュールの変数とかにアクセスするときには、名前空間の解決が必須。from文を使った場合には、その必要がないと言うこと。


例えば、次のようなモジュールをfrom_test.pyという名前で作成したとする。

X = 0
Y = [1]

def test_func():
    print 'test_func() was called.'

これをpythonのプロンプトから使ってみる。まずimport文。

bash-3.2$ python
Python 2.5.1 (r251:54863, Feb  6 2009, 19:02:12)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import from_test
>>> from_test.test_func()
test_func() was called.

こんな感じである。from_testモジュールの中で定義された関数、test_func()を呼び出すのに、

from_test.test_func()

としていることに注意。名前解決はプログラマが自分でする必要がある。続いてfrom文を使ってみる。
from文の書式は、”from モジュール名 import インポート対象”である。

bash-3.2$ python
Python 2.5.1 (r251:54863, Feb  6 2009, 19:02:12)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from from_test import test_func
>>> test_func()
test_func() was called.

こんな風になる。from_testモジュールで定義されている関数test_func()を直接呼び出せる。from文を使った場合には、名前解決をプログラマが行う必要はない。from文では、インポート対象を自分の名前空間にコピーするためだ。
上記のfrom文の例に続けて、XとYもfrom文でインポートしてみる。

>>> from from_test import X, Y
>>> X
0
>>> Y
[1]
>>>

こんな具合である。

ここで、これらを書き換えたらどうなるのか確かめてみたい。
まずは、さらに同じpythonプロンプト上で、from_testモジュールをimportする。
これは問題なく行うことが可能。

>>> import from_test

問題はこの後である。X と Y にそれぞれ値を代入してみる。

>>> X = 100
>>> Y = 200
>>> X, Y
(100, 200)

普通に代入を行うことが可能だが、このとき、モジュール側名前空間にある変数には影響があるのかどうか。

>>> from_test.X
0
>>> from_test.Y
[1]

この通りである。from文を使った場合には、自分の名前空間に同じ名前の変数をコピー、つまり作成するので、元モジュールに存在する変数の保持する内容が書き換わってしまうことはない。では、次のような書き換え方をするとどうなるかやってみる。代入対象はYだけである。

>>> from from_test import X, Y
>>> import from_test
>>> Y
[1]
>>> Y[0] = 5
>>> Y
[5]
>>> from_test.Y
[5]

まず、from、importを行った後、ローカルアクセスしているYの保持しているリストの、0番目の要素を5に書き換える、という処理を行っている。
この場合には、元のモジュール内にあるYの保持しているリストの内容も変わってしまうので注意が必要だ。どうしてこうなるかというと、from文でYをコピーしたときに、ローカル名前空間にコピーされたYが保持しているのは、元のモジュール内で初期化に使用しているリストへの参照だからである。

Y[0] = 5

この文は、Yが保持しているリストへの参照を使って、要素0を書き換えている。この参照は、元モジュール中のYも保持している参照なので、要素は書き換わってしまう。一方、下のコードでは、変数が保持している参照自体が書き換わってしまうので、元のモジュールに影響はない。

X = 5

こちらの場合には、最初にローカル名前空間のXが保持しているのは、元モジュール中のXが保持しているのと同じ参照だが、X=5という文で、数値5への参照が代入される。これは、元モジュールに影響するものではないため、元モジュールのXが保持している値はそのままである。

bash-3.2$ python
Python 2.5.1 (r251:54863, Feb  6 2009, 19:02:12)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from from_test import X
>>> import from_test
>>> X
0
>>> X = 5
>>> X
5
>>> from_test.X
0

このように、Xの値は5に変わるが、from_test.Xは、依然として0である。元モジュールのXの値を書き換えるには、from_test.Xに対して代入を行えばいい。

そして関数はどうなるか。これは簡単である。fromでコピーされるのは、関数オブジェクトへの参照である。だから、元モジュールの関数オブジェクトを参照している変数が一つ増えるというだけだ。

bash-3.2$ python
Python 2.5.1 (r251:54863, Feb  6 2009, 19:02:12)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from from_test import test_func
>>> import from_test
>>> test_func

>>> from_test.test_func

こんな感じで同じ関数オブジェクトを参照している。

これらの点に気をつけて使えば、from文は、名前解決をせずに他モジュール内の変数とか関数とか使用できるので、プログラミングの手間が省ける(モジュール名を全部入力しなくて済む)。
ただし、乱用するとローカル名前空間にごちゃごちゃと変数が増えてしまうし、それらの定義されている場所がどこなのか探すのが非常に困難になってしまう。いきなり変数名が書いてあるばかりでローカル変数何だかなんなのか、後から解析する際に非常につらいので、乱用は避けたい。使いたいポイント、使うべきポイントで効果的に使うようにしないといけない、と。

モジュールについては、もう少し続く予定。





トラックバックURL


この記事に対するコメント/トラックバックはまだありません


コメントをどうぞ

お名前(必須)
Eメールアドレス(公開されません)(必須)