StoryEdit 開発日誌

ウェブアプリ StoryEditを作ってましたが延期。普通のブログ。

Python __all__について

なんか,役に立つのか立たないのか微妙なところになってきた.

__all__は,モジュールの外に公開するかしないかを決める,C言語でもがんばって関数の公開,非公開を無理矢理記述するように,結局シンボルテーブルを変更する,,,らしい.

その動作を知るためにサンプルを書いてみる.まず,テスト用のパッケージを書く.

#hoge/hoge.py
def h1(a):
	return a;

def h2(a):
	return a+1;

上の関数をもつ,hogeパッケージ(hogeモジュールのみ)を作ってみる.
んで,これを呼び出す部分.

#hogemain.py
from hoge.hoge import h1, h2;

print h1(2);
print h2(2);
$ python hogemain.py 
2
3

まぁいいですね.

では,__all__を使ってみる.例えば,h2を公開したくない!と言う場合.

#hoge/hoge.py
__all__ = ['h1'];
def h1(a):
	return a;

def h2(a):
	return a+1;
$ python hogemain.py 
Traceback (most recent call last):
  File "hogemain.py", line 2, in <module>
    from hoge.hoge import h1, h2;
ImportError: cannot import name h2

これは,「明示的に使う関数を宣言する」というPythonのお勧めするクリーンなコードだったため,importステートメントではねてくれています.しかし,現実は,hogemain.pyは以下のように書かれる可能性も.

from hoge.hoge import *;
##from hoge.hoge import h1, h2;

print h1(2);
print h2(2);

するとどうなるか,といいますと,

Traceback (most recent call last):
  File "hogemain.py", line 5, in <module>
    print h2(2);
NameError: name 'h2' is not defined

先ほどとはエラーの出る箇所が替わりました.これでうまくh2を隠蔽できています.h2をシンボルテーブルにのせない方法はもう一つあって,__all__を書かずに,関数名を_h2とする方法です.こちらのほうがソースコードの途中をみても,その関数の使途がわかるので好きかも.

ちなみに,__all__法はfrom (module) import * 以外,たとえばimport (module)では無視されるそうです.

import hoge.hoge;

print hoge.hoge.h1(2);
print hoge.hoge.h2(2);
$ python hogemain.py 
2
3

こちらも__all__の指定はそのままなのですが,h2は呼べちゃっています.hoge.hogeという名前空間があるため,特に隠蔽の必要がないのですね.fromを使った,自分の名前空間へのロードの場合のみ作用する,という仕様みたいです.

さて,使いどころですが,モジュールから出すシンボルが多いとすべてのリストアップは厄介です.個人的には_を使う方が良い気がしています.あとは,パッケージ内のモジュール名を__init__.pyに__all__で記述しておいて,一部隠蔽する,という使い方もあるみたいです.