今日もぶりぶりお勉強。
今日はモジュールのインポートについてやる。
まずは、、、
モジュールの作成
モジュールは主にテキストエディタなどで作成するのが普通とのこと。テキストファイルにPythonのコードを入力する。
モジュール内の「トップレベル」で値が代入された変数(名前)は、そのモジュールの「属性」となる。
ちなみに、モジュールをインポートする側のコードのことを「クライアント」と言う。
で、クライアントからはその「属性」を利用できる。
モジュールのファイル名は.py拡張子をつけておく。
モジュールのファイル名のうち、.py拡張子を省いた部分が「モジュールの名前」となる。
したがって、モジュールのファイル名は変数名命ルールに従ってつける必要がある。
さらにモジュールを置いておくディレクトリ名も変数命名ルールに従っておくのが無難とのこと。
モジュールを利用する。
利用するにはimportステートメントかfromステートメントを使う。
importとfromの違いは、ざっくりと
- importステートメント -- モジュール全体を取り込む
- fromステートメント -- モジュール中の特定の属性だけをコピーする
importステートメントでモジュールを利用する
モジュールを「module1.py」というファイル名で作成したとする。
中身は
$ cat module1.py
print "start loading"
def aaa(x):
print 'Hello,',x
print "loaded"
$
となっていたとする。
トップレベルからインポートしてみる。
$ python
Python 2.4.4 (#2, Apr 5 2007, 20:11:18)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import module1.py
start loading
loaded
Traceback (most recent call last):
File "", line 1, in ?
ImportError: No module named py
import module1.pyと入力するとエラーになる。import、fromでは.py拡張子をつけずにモジュール名
を指定しなければならない。
上記のように.py拡張子をつけてインポートすると、どういうことになるかというと、
module1モジュールのpy属性をインポートする
という意味になってしまう。
さらにimportステートメントなのでpy属性はモジュールである必要がある。
気を取り直して、
$ python
Python 2.4.4 (#2, Apr 5 2007, 20:11:18)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import module1
start loading
loaded
>>> module1.aaa('world')
Hello, world
>>>
.py拡張子をつけずにimportし、その後module1モジュールのaaa属性を呼び出した。
module1の属性を利用するには、利用するたびに"module1."と、モジュール名を指定する必要がある。
fromステートメントでモジュールを利用する。
次はfromステートメントでモジュールを利用してみる。
利用するモジュールは上記のmodule1.py。
$ python
Python 2.4.4 (#2, Apr 5 2007, 20:11:18)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from module1 import aaa
start loading
loaded
>>> aaa('world')
Hello, world
>>>
こんどはmodule1モジュールのaaa属性のみを抽出した。
importと違うのはfromでは、
カレントスコープにimport以降で指定した属性をコピーする
ということらしい。
よって、モジュール名を指定しなくてもモジュールの属性を利用できる。
コピーなので、
>>> aaa = (lambda x: 'hi,' + x)
>>> aaa('world')
'hi,world'
>>>
などとやっても、module1の方のaaa属性は影響を受けない。
ただし、aaaが仮に共有リファレンスであった場合、つまりリストなどであった場合はその要素に対する変更がモジュール側にも影響を及ぼす。
$ cat module1.py
print "start loading"
def aaa(x):
print 'Hello,',x
bbb = [1,2,3,4,5]
print "loaded"
のようにbbb属性をリストで追加した。
そしてこれを
$ python
Python 2.4.4 (#2, Apr 5 2007, 20:11:18)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from module1 import bbb
start loading
loaded
>>> bbb
[1, 2, 3, 4, 5]
>>> bbb[0]=10
>>> bbb
[10, 2, 3, 4, 5]
と0番目の要素を上書きする。
モジュール側はどうなっているかというと、
>>> import module1
>>> module1.bbb
[10, 2, 3, 4, 5]
>>>
と、bbbの0番目の要素が10に上書きされている。
つまりbbbそのものはコピーされたが、bbbの保持する各要素はリファレンスをそのまま引き継いでいる
ということ。
この辺は他の変数に対するリファレンスの扱いと一緒。
from *ステートメントでモジュールを利用する。
fromステートメントで、import以降に'*'を指定すると、「全ての属性」をコピーする。
module1は1つしか属性がないが、、、
$ python
Python 2.4.4 (#2, Apr 5 2007, 20:11:18)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from module1 import *
start loading
loaded
>>> aaa('hello')
Hello, hello
>>>
などと指定すると、module1の中の全属性がカレントスコープにコピーされる。
インポートしたモジュールの属性へのアクセス
インポートしたモジュールの属性を利用する際にもPython側で属性の特定ルールが存在する。
単純な変数の場合
LEGBルールによって変数がいずれかのスコープから検索される。
完全名の場合
module1.aaaのように書くと、カレントスコープでmodule1が検索され、
その後module1にaaaという属性がないか検索される。
完全パス名の場合
module1.aaa.bbbのように書くと、カレントスコープでmodule1が検索され、
その後module1にaaaという属性がないか検索され、
次にmodule1.aaaにbbbという属性がないか検索される。
な感じにルールがある。
完全名は、モジュールの他にクラス、Cの型など属性を持つ全てのオブジェクトに使用できる。
おしまい。
.
0 コメント:
コメントを投稿