目次

前のトピックへ

一般 Python FAQ

次のトピックへ

デザインと歴史 FAQ

このページ

プログラミング FAQ

Contents

一般的な質問

ブレークポイントやシングルステップ実行などを備えたソースコードレベルデバッガはありますか?

はい。

pdb モジュールは簡素にして十分な Python のコンソールモードデバッガです。これは Python の標準ライブラリに含まれているもので、 ライブラリリファレンスマニュアルにドキュメントがあります。 pdb のコードを手本にして自分用のデバッガを書くこともできます。

Python に同梱されている統合開発環境の IDLE は 通常の Python の配布形態の一部 (普通は Tools/scripts/idle から利用可能) であり、グラフィカルなデバッガを含んでいます。IDLE デバッガのドキュメントは http://www.python.org/idle/doc/idle2.html#Debugger にあります。

PythonWin は、pdb をベースとした GUI デバッガを含む Python IDE です。 Pythonwin デバッガは、ブレークポイントの色付けや非 Pythonwin プログラムのデバッグなどのたくさんの素敵な機能を持っています。Pythonwin は Python for Windows Extensions プロジェクトの一部、あるいは ActivePython ディストリビューション (http://www.activestate.com/Products/ActivePython/index.html を参照) の一部として利用可能です。

Boa Constructor は、 wxWidgets を使った IDE と GUI ビルダーです。これは視覚フレームの作成と操作、オブジェクト検査、オブジェクトブラウザのような多くのビュー、継承構造、 doc string から生成される html ドキュメント、高度なデバッガ、総合ヘルプ、 Zope のサポートを提供します。

Eric は PyQt や Scintilla editing component をもとにした IDE です。

Pydb は標準のデバッガである pdb を人気のグラフィカルデバッガフロントエンドである DDD (Data Display Debugger) とともに使うために改変したものです。Pydb は http://bashdb.sourceforge.net/pydb/ に、 DDD は http://www.gnu.org/software/ddd にあります。

商業のグラフィカルデバッガ付き Python IDE もあります。例えば:

バグの発見や静的分析に役立つツールはありますか?

はい。

PyChecker は Python ソースコードのバグを発見しコードの複雑さとスタイルについて警告する静的解析ツールです。PyChecker は http://pychecker.sf.net から手に入ります。

Pylint は、モジュールがコーディング標準を満たすかを調べ、プラグインを書いてカスタム機能を加えられるようにするツールです。PyChecker が行うバグチェックに加え、 Pylint は行の長さ、変数名が一貫しているか、宣言されたインタフェースが完全に実装されているか、などを確かめる追加の機能を提供します。 http://www.logilab.org/card/pylint_manual から Pylint の機能の一覧を見られます。

どうしたら Python スクリプトからスタンドアロンバイナリを作れますか?

ユーザがダウンロードや起動のために Python ディストリビューションをインストールしなくてもよいスタンドアロンプログラムのためだけなら、 Python を C コードにコンパイルできる必要はありません。プログラムに対して必要なモジュールを選び、そのモジュールを Python バイナリに束縛して一つの実行可能ファイルにまとめる多くのツールがあります。

一つは freeze ツールで、Python ソースツリーに Tools/freeze として含まれています。これは Python バイトコードを C 配列に変換します。すべてのモジュールを標準 Python モジュールにリンクされる新しいプログラムに埋め込む C コンパイラです。

これはあなたのソースの (両方の形式の) import 文を再帰的にスキャンして、 import されたモジュールを標準の Python パスと (組み込みモジュールのある) ソースディレクトリから探します。そして Python で書かれたモジュールのバイトコードを C コード (marshal モジュールでコードオブジェクトに変換できる配列) に変換し、実際にそのプログラム内で使われている組み込みモジュールだけが含まれたカスタムメイドの設定ファイルを作成します。そして生成された C コードをコンパイルして Python インタプリタの残りとリンクし、元のスクリプトと全く同じように動作する自己充足的なバイナリを形成します。

もちろん、凍結には C コンパイラが必要です。C コンパイラを必要としない選択肢もあります。その一つは、Thomas Heller の py2exe (Windows 専用) です。

他に、 Christian Tismer の SQFREEZE は、実行可能ファイルのバイトコードを探すことができる特別な Python インタプリタにバイトコードを加えます。

その他のツールには、Fredrik Lundh の Squeeze や Anthony Tuininga の cx_Freeze などがあります。

Python プログラムのためのコーディングスタンダードやスタイルガイドはありますか?

はい。標準ライブラリモジュールに求められるコーディングスタイルは PEP 8 として文書化されています。

プログラムが遅すぎます。どうしたら速くなりますか?

一般に、それは難しい質問です。Python コードを速くするためには、いろいろな手法があります。最終手段として一部を C で書き直す事も考えてください。

Python を自動的に C や x86 アセンブリ言語に変換できる場合もあります。この場合、速度を上げるためにコードを変更する必要はありません。

Pyrex は Python コードの少し変化した版を C 拡張にコンパイルでき、多様なプラットフォームで使えます。

Psyco は Python コードを x86 アセンブリ言語に変換する実行時コンパイラです。これを使うことが出来れば、重要な関数を劇的にスピードアップできます。

あとは、Python コードからもう少し速度を搾り出すための様々な手法について議論することになります。コード中の特定の関数が処理が集中するホットスポットで、最適化が必要であると認められない限り、決して いかなる最適化の手法も使わないでください。最適化はたいていコードを分かりづらくするので、分かりづらさのコスト (開発時間の延長とバグの可能性の増大) がそれに見合ったパフォーマンスの向上につながらないのであれば元が取れません。

performance tips に関するページが wiki にあります。

Guido van Rossum は http://www.python.org/doc/essays/list2str.html で最適化に関する逸話を詳述しています。

なお、関数や(特に)メソッドの呼び出しはかなり高価です。インスタンス変数を get や set したり他のメソッドを呼び出す程度の小さな関数がたくさんある純粋 OO インタフェースをデザインしているなら、インスタンス変数に直接アクセスするようなもっと直接的な方法も考えてみてください。また、どのプログラムが実行時間の大部分を占めているかを見つける標準モジュール profile も参照してください (ちょっと忍耐できればの話ですが - プロファイリングはそれ自体がプログラムを一桁ほど遅くしてしまいます)。

もちろん、他のプログラミングの経験から得られた多くの標準的な最適化の発見的手法は Python にもよく当てはまることが多いです。たとえば、出力装置に出力を送るときに、一度に少なく書くよりもむしろ多く書いたほうが、カーネルのシステムコールのオーバーヘッドを減らすことができて、速くなるでしょう。したがって、CGI スクリプトは “一発” ですべて書き出すもののほうが小さなたくさんの出力に分けて書き出すものよりも速くなるでしょう。

また、必ず Python のコアな機能を適切に使ってください。例えば、スライシングなら、リストや他のシーケンスオブジェクトを、高度に最適化された C 実装で、インタプリタのメインループの一刻みで細切れにできます。こうして効果を得ることができる例は:

L2 = []
for i in range[3]:
    L2.append(L1[i])

こう使えばずっと短く、ずっと速くできます:

L2 = list(L1[:3])  # "list" is redundant if L1 is a list.

関数指向組み込み関数 map() や zip() なども一つのタスクを実行するためのループを加速するのに便利であることに注意してください。例えば、二つのリストの要素を組み合わせるためには:

>>> zip([1, 2, 3], [4, 5, 6])
[(1, 4), (2, 5), (3, 6)]

また、正弦を一度に計算するには:

>>> map(math.sin, (1, 2, 3, 4))
[0.841470984808, 0.909297426826, 0.14112000806, -0.756802495308]

このような場合には素早く演算が完了します。

その他の例には、文字列オブジェクトのメソッド join() 、split() などが挙げられます。

例えば s1..s7 が大きな (10K+) 文字列の時、"".join([s1,s2,s3,s4,s5,s6,s7]) は単純に s1+s2+s3+s4+s5+s6+s7 とするよりもはるかに速くなるでしょう。なぜなら、join() はすべてのコピーを一括して行うのに対し、「足し算」が多くの副演算を行うからです。文字列を扱うには、 文字列オブジェクトのメソッド replace()、 format() を使ってください。正規表現を使うのは、決まった文字列のパターンを使わない時だけにしてください。 旧式の % 演算 string % tuple と string % dictionary も使えます。

ソートには必ずビルトインオブジェクトの list.sort() を使ってください。また、sorting mini-HOWTO の少し高度な使い方の例を参照してください。list.sort() は、よほど極端な状況でない限り、他のソートの技術に勝ります。

「ループを関数やメソッドの中に入れ込む」というのも一般的な手法です。例えば、遅いプログラムがあって、Python の ff() 関数が何度も呼ばれていることがプロファイラで分かったとします。もし、ff():

def ff(x):
    ... # do something with x computing result...
    return result

が:

list = map(ff, oldlist)

または:

for x in sequence:
    value = ff(x)
    ... # do something with value...

のようにループの中で呼ばれていることが多いなら、ff() を:

def ffseq(seq):
    resultseq = []
    for x in seq:
        ... # do something with x computing result...
        resultseq.append(result)
    return resultseq

のように、また、上の二つの例を、list = ffseq(oldlist) と:

for value in ffseq(sequence):
    ... # do something with value...

のように書き換えることによって、関数を呼ぶためのオーバーヘッドを省けることが多いです。

ff(x) を一回だけ呼ぶ場合、 ffseq([x])[0] に直してしまうとちょっと不利になります。 もちろん、このテクニックがいつでも適切であるわけではありませんし、解決のための他の方法もあります。

関数やメソッドの探索の結果をローカル変数に明示的に保存すると少しパフォーマンスが良くなります。次のようなループ:

for key in token:
    dict[key] = dict.get(key, 0) + 1

は、繰り返しのたびに dict.get を求めています。 このメソッドが変わることがないのなら、少し速い実装は:

dict_get = dict.get  # look up the method once
for key in token:
    dict[key] = dict_get(key, 0) + 1

デフォルト引数は、実行時でなく、コンパイル時に値を一回で決めてしまうのに使えます。これは、プログラムの実行中に変化しない関数やオブジェクト、例えば:

def degree_sin(deg):
    return math.sin(deg * math.pi / 180.0)

を、次のように置き換えるときにのみ行えます:

def degree_sin(deg, factor=math.pi/180.0, sin=math.sin):
    return sin(deg * factor)

この手法はデフォルト引数が変えられないことを前提に使うので、ユーザーが API で混乱するおそれがないときのみ使えます。

コア言語

なぜ変数に値があるのに UnboundLocalError が出るのですか?

もともと動いていたコードが、関数の本体のどこかに代入文を加えるという変更をしたら UnboundLocalError を出すのには驚くかもしれません。

このコード:

>>> x = 10
>>> def bar():
...     print x
>>> bar()
10

は動きますが、このコード:

>>> x = 10
>>> def foo():
...     print x
...     x += 1

は UnboundLocalError になります:

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment

これは、あるスコープの中で変数に代入を行うとき、その変数はそのスコープに対してローカルになり、外のスコープにある同じ名前の変数を隠すからです。 foo の最後の文が x に新しい値を代入しているので、コンパイラはこれをローカル変数であると認識します。その結果、先の print x が初期化されていないローカル変数を表示しようとして結果はエラーとなります。

上の例では、グローバルであると宣言することで外のスコープにアクセスできます:

>>> x = 10
>>> def foobar():
...     global x
...     print x
...     x += 1
>>> foobar()
10

この明示的な宣言は (表面的には似ているクラスとインスタンス変数の例とは違って) あなたは実際は他のスコープの変数の値を変えようとしているのだ、ということを知らせるのに必要です:

>>> print x
11

Python のローカルとグローバル変数のルールは何ですか?

Python では、関数の中で参照のみされる変数は暗黙のうちにグローバルになります。関数の本体のどこかで新しい値が変数に代入されたなら、それはローカルであるとみなされます。関数の中で新しい値が一度でも代入されたらその変数は暗黙のうちにローカルであり、’global’ は明示的に宣言しなければなりません。

最初はちょっと驚くでしょうが、少し考えると納得できます。一方では、代入された変数に global を要求することで、意図しない副作用を防げます。他方では、グローバルな参照の度に global が要求されてしまうと、 global を使ってばかりになってしまいます。ビルトイン関数やインポートされたモジュールの内容を参照するたびにグローバル宣言をしなければならないのです。その乱雑さは副作用を特定するための global 宣言の便利さよりも重大です。

グローバル変数をモジュール間で共有するにはどうしたらいいですか?

一つのプログラムのモジュール間で情報を共有する正準な方法は、特別なモジュール (しばしば config や cfg と呼ばれる) を作ることです。単に設定モジュールをアプリケーションのすべてのモジュールにインポートしてください。このモジュールはグローバルな名前として使えます。それぞれのモジュールのただ一つのインスタンスがあるので、設定モジュールオブジェクトに対するいかなる変更も全体に反映されます。例えば:

config.py:

x = 0   # Default value of the 'x' configuration setting

mod.py:

import config
config.x = 1

main.py:

import config
import mod
print config.x

なお、同じ理由から、モジュールを使うということは、シングルトンデザインパターンを実装することの基礎でもあります。

モジュールで import を使う際の「ベストプラクティス」は何ですか?

一般に、from modulename import * を使わないでください。使うとインポータの名前空間を混乱させてしまいます。この書式でインポートされるように設計された数少ないモジュールにすらこの構文を使わないようにする人もいます。そのように設計されたモジュールには Tkinter や threading などがあります。

モジュールはファイルの先頭でインポートしてください。これによってコードが必要とする他のモジュールが明確になり、モジュール名がスコープに含まれるかどうかに迷わなくなります。行に一つのインポートにすると、モジュールのインポートの追加と削除が容易になりますが、行に複数のインポートにすると画面の領域が少なく済みます。

次の手順でモジュールをインポートするのが、良いプラクティスになります:

  1. 標準ライブラリモジュール – 例 sys、os、getopt、re
  2. サードパーティのライブラリモジュール (Python の site-packages ディレクトリにあるもの) – 例 mx.DateTime、ZODB、PIL.Image、など
  3. 内部で開発したモジュール

相対インポートは決して使わないでください。package.sub.m1 モジュールのコードを書いていて、package.sub.m2 をインポートしようとするとき、 from . import m2 とだけ書くのは、違反ではありませんがやらないでください。代わりに from package.sub import m2 と書いてください。詳細は PEP 328 を参照してください。

循環参照の問題を避けるために、インポートを関数やクラスに移すことが必要なときもあります。Gordon McMillan によれば:

循環参照は両方のモジュールが “import <module>” 形式のインポートを使っていれば大丈夫です。二つ目のモジュールが最初のモジュールから名前を確保しようとして (“from module import name”)、そのインポートがトップレベルにあると駄目です。最初のモジュールが二つ目のモジュールをインポートするのに忙しくて、最初のモジュールの名前が利用可能になっていないからです。

この状況では、二つ目のモジュールが一つの関数の中でのみ使われているならば、そのインポートは簡単に関数の中に移せます。インポートが呼ばれたとき、最初のモジュールは初期化を完了していて、二つ目のモジュールは自分のインポートをできます。

プラットフォーム依存のモジュールがあるときには、インポートをトップレベルの外に動かすことも必要です。この場合、ファイルの先頭ではすべてのモジュールをインポートすることさえできないかもしれません。この場合は、対応するプラットフォームに合わせたコードで正しいモジュールをインポートすることを選ぶと良いです。

循環参照の問題を避けたりモジュールの初期化にかかる時間を減らしたりしたいなら、単にインポートを関数定義の中などのローカルなスコープに移してください。この手法は多くのインポートがプログラムがどのように実行されるかに依存しなくてよいときに特に有効です。ある関数の中でのみモジュールが使われるのなら、インポートをその関数の中に移すことを考えてもいいでしょう。なお、モジュールを読み込む最初の回はモジュールの初期化の時間のために高価になりえますが、複数回目にモジュールを読み込むのは事実上無料、辞書探索の数回のコストだけで済みます。モジュール名がスコープから外れてさえ、そのモジュールはおそらく sys.modules から利用できるでしょう。

特定のクラスのインスタンスのみがあるモジュールを使っているなら、そのクラスの __init__ メソッドでそのモジュールをインポートし、そこでインスタンス変数にそのモジュールを代入して、オブジェクトがある間そのモジュールがいつでも (インスタンス変数を経由して) 利用できるようにするのが合理的です。なお、インポートをクラスが初期化される時まで先送りにするためには、インポートはメソッドの中にないといけません。インポートをクラスの中に入れてもメソッドの外に出してしまうと、そのインポートはモジュールの初期化の時になされてしまいます。

オプションパラメタやキーワードパラメタを関数から関数へ渡すにはどうしたらいいですか?

関数のパラメタリストに引数を * と ** 指定子 (specifier) で集めてください。そうすれば、固定引数をタプルとして、キーワード引数を辞書として得られます。これで、他の関数を呼び出すときに * と ** を使ってそれらの引数を渡せます:

def f(x, *args, **kwargs):
    ...
    kwargs['width'] = '14.3c'
    ...
    g(x, *args, **kwargs)

あまりありませんが、Python の 2.0 以前のバージョンを考慮するときは、代わりに apply() を使ってください:

def f(x, *args, **kwargs):
    ...
    kwargs['width'] = '14.3c'
    ...
    apply(g, (x,)+args, kwargs)

パラメタを出力する関数 (参照渡し) はどのように書きますか?

前提として、Python では引数は代入によって渡されます。代入はオブジェクトへの参照を作るだけなので、呼び出し元と呼び出し先にある引数名の間にエイリアスはありませんし、参照渡しそれ自体はありません。望む効果を得るためには幾つかの方法があります。

  1. 結果のタプルを返すことによって:

    def func2(a, b):
        a = 'new-value'        # a and b are local names
        b = b + 1              # assigned to new objects
        return a, b            # return new values
    
    x, y = 'old-value', 99
    x, y = func2(x, y)
    print x, y                 # output: new-value 100
    

    これはたいてい一番明確な方法です。

  2. グローバル変数を使って。これはスレッドセーフでないので、推奨されません。

  3. ミュータブルな (インプレースに変更可能な) オブジェクトを渡すことによって:

    def func1(a):
        a[0] = 'new-value'     # 'a' references a mutable list
        a[1] = a[1] + 1        # changes a shared object
    
    args = ['old-value', 99]
    func1(args)
    print args[0], args[1]     # output: new-value 100
    
  4. 変更される辞書に渡すことによって:

    def func3(args):
        args['a'] = 'new-value'     # args is a mutable dictionary
        args['b'] = args['b'] + 1   # change it in-place
    
    args = {'a':' old-value', 'b': 99}
    func3(args)
    print args['a'], args['b']
    
  5. クラスインスタンスに値を同梱することによって:

    class callByRef:
        def __init__(self, **args):
            for (key, value) in args.items():
                setattr(self, key, value)
    
    def func4(args):
        args.a = 'new-value'        # args is a mutable callByRef
        args.b = args.b + 1         # change object in-place
    
    args = callByRef(a='old-value', b=99)
    func4(args)
    print args.a, args.b
    

    このような複雑なことをする理由はめったに無いでしょう。

一番の選択は、複数の結果を含むタプルを返すことです。

Python で高次関数はどのようにつくりますか?

二つの方法があります: ネストされたスコープを使う方法と、呼び出し可能オブジェクトを使う方法です。例えば、a*x+b の値を計算する f(x) 関数を返す linear(a,b) を定義したいとします。ネストされたスコープを使うと:

def linear(a, b):
    def result(x):
        return a * x + b
    return result

また、呼び出し可能オブジェクトを使うと:

class linear:

    def __init__(self, a, b):
        self.a, self.b = a, b

    def __call__(self, x):
        return self.a * x + self.b

どちらの場合でも:

taxes = linear(0.3, 2)

とすれば、taxes(10e6) == 0.3 * 10e6 + 2 となるような呼び出し可能オブジェクトを得られます。

呼び出し可能オブジェクトを使う方法は、少し遅くなり、わずかにコードが長くなるという短所があります。ですが、継承を使ってコーラブル同士で記号を共有することもできます:

class exponential(linear):
    # __init__ inherited
    def __call__(self, x):
        return self.a * (x ** self.b)

オブジェクトはいくつかのメソッドに状態をカプセル化できます:

class counter:

    value = 0

    def set(self, x):
        self.value = x

    def up(self):
        self.value = self.value + 1

    def down(self):
        self.value = self.value - 1

count = counter()
inc, dec, reset = count.up, count.down, count.set

ここで、inc()、dec() 、reset() は同じカウント変数を共有する関数のようにふるまいます。

Python のオブジェクトはどのようにコピーしますか?

一般的に、普通は copy.copy() や copy.deepcopy() を試してください。何でもコピーできるとは限りませんが、たいていはできます。

もっと簡単にコピーできるオブジェクトもあります。辞書には copy() メソッドがあります:

newdict = olddict.copy()

シーケンスはスライシングでコピーできます:

new_l = l[:]

オブジェクトのメソッドや属性はどのように見つけますか?

ユーザー定義クラスのインスタンス x で、dir(x) はインスタンス属性とそのクラスで定義されたメソッドや属性を含む名前のアルファベット順リストを返します。

コードはどのようにオブジェクトの名前を見つけるのですか?

概して、オブジェクトは本当は名前を持たないので、見つけることはできません。本質的には、代入とはいつも値に名前を束縛することです。def と class 文も同じですが、この場合は値はコーラブルです。以下のコードを考えてみましょう:

class A:
    pass

B = A

a = B()
b = a
print b
<__main__.A instance at 0x16D07CC>
print a
<__main__.A instance at 0x16D07CC>

おそらく、このクラスには名前があります。このクラスは二つの名前に縛られて、名前 B を通して呼び出されますが、それでもクラス A のインスタンスとして報告されるのです。しかし、両方の名前が同じ値に束縛されている以上、このインスタンスの名前が a か b か決めることはできないのです。

概して、コードにとってある値の「名前を知っている」事は重要ではありません。あなたがわざと内省的なコードを書いているのでない限り、方針を変えた方がいいかもしれないということになるでしょう。

comp.lang.python で、Fredrik Lundh はこの問題の答えとして素晴らしい喩えをしてくれました:

玄関にいた猫の名前を知るのと同じ方法です: その猫 (オブジェクト) 自体はその名前を言うことができないし、それは実は問題ではありません – その猫が何と呼ばれているかを知る唯一の方法は、すべての隣人 (名前空間) にその猫(オブジェクト)が何と呼ばれているかを聞くことです。

……そして、その猫が沢山の名前で知られていたり、逆に全く名前が全く無かったりしても驚かないでください!

カンマ演算子はなぜ優先されるのですか?

カンマは Python では演算子ではありません。このセッションを考えてください:

>>> "a" in "b", "a"
(False, 'a')

カンマは演算子ではなく、式の分離子なので、上の式は次の式と同じように評価されます:

>>> ("a" in "b"), "a"

次のようには評価されません:

>>> "a" in ("b", "a")

他のさまざまな演算子(=、+= など)も同じです。これらは真の演算子ではありませんが、代入文の構文上のデリミタです。

Is there an equivalent of C’s ”?:” ternary operator?

はい、この機能は Python 2.5 で追加されました。構文は以下のようになります:

[on_true] if [expression] else [on_false]

x, y = 50, 25

small = x if x < y else y

2.5 以前のバージョンに関しては、答えは「いいえ」です。

多くのケースでは a and b or c で a ? b : c の代わりをできますが、これでは漏れがあります。b が 0 (あるいは空、または None – 偽となるものすべて) のとき、c が代わりに選ばれてしまいます。多くの場合にはコードからこれが起こらないと解ります( 例えば、b が定数だったり、決して偽にならない型だったりするので) が、これは大体問題になり得ます。

Tim Peters (who wishes it was Steve Majewski) は次の解決策を提案しました。 (a and [b] or [c])[0]。[b] は一つの要素を持つリストであり、決して偽とならないので、間違った経路を通りません。だから [0] を全体に適用すれば、本当に欲しかった b または c が得られます。醜いですが、’if’ を使って書き換えるのがどうしても不便な特殊な場合には、これで目的が達成できます。

一番の方法はたいてい、単純に if...else 文を書くことです。あるいは、 ?: 演算子を関数として実装する方法もあります:

def q(cond, on_true, on_false):
    if cond:
        if not isfunction(on_true):
            return on_true
        else:
            return on_true()
    else:
        if not isfunction(on_false):
            return on_false
        else:
            return on_false()

たいてい、b と c は q(a, b, c) のように直接渡すことになります。 b や c が評価されるべきでないとき、評価を避けるには、 q(a, lambda: b, lambda: c) のようにラムダ関数に包んでください。

なぜ Python に if-then-else 式が無いのかは問われていました。答えはいくつかあります。多くの言語はそれ無しで十分なこと、読みにくいコードになりやすいこと、十分「Pythonic」な構文が見当たらないこと、標準ライブラリには if-then-else 式で表すとコードが分かりやすくなるような箇所がほとんどないことです。

2002年、いくつかの構文の選択肢を提案する PEP 308 が書かれ、コミュニティはこの論点について投票を行いました。多くの人はそれぞれある構文を好み、また他の構文を嫌いました。投票者の多くが、自分の嫌いな構文を取り入れるくらいなら、三項演算子を取り入れないほうがいいと考えました。

Python で解し難いワンライナーを書くことはできますか?

はい。そういうものはたいてい、lambda の中に lambda がネストされています。Ulf Bartelt による下の3つの例を見てください:

from functools import reduce

# Primes < 1000
print filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,
map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000)))

# First 10 Fibonacci numbers
print map(lambda x,f=lambda x,f:(f(x-1,f)+f(x-2,f)) if x>1 else 1: f(x,f),
range(10))

# Mandelbrot set
print (lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,
Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,
Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,
i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=lambda xc,yc,x,y,k,f:(k<=0)or (x*x+y*y
>=4.0) or 1+f(xc,yc,x*x-y*y+xc,2.0*x*y+yc,k-1,f):f(xc,yc,x,y,k,f):chr(
64+F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i)),range(Sx))):L(Iu+y*(Io-Iu)/Sy),range(Sy
))))(-2.1, 0.7, -1.2, 1.2, 30, 80, 24)
#    \___ ___/  \___ ___/  |   |   |__ lines on screen
#        V          V      |   |______ columns on screen
#        |          |      |__________ maximum of "iterations"
#        |          |_________________ range on y axis
#        |____________________________ range on x axis

よい子はまねしないでね!

数と文字列

十六進数や八進数を指定するにはどうしたらいいですか?

八進数を指定するには、八進数での値の先頭に 0 と “o” (小文字または大文字) を加えてください。たとえば、変数 “a” に八進数での “10” (十進数での”8”) を代入するには、こう打ってください:

>>> a = 0o10
>>> a
8

十六進数も簡単です。ただ十六進数での値の先頭に 0 と “x” (小文字または大文字) を加えてください。十六進数は小文字でも大文字でも指定できます。たとえば、Python インタプリタで:

>>> a = 0xa5
>>> a
165
>>> b = 0XB2
>>> b
178

なぜ -22 // 10 は -3 を返すのですか?

i % j が j と同じ符号であってほしいことに基づいています。それに加えて以下のようにもしたいとすると:

i == (i // j) * j + (i % j)

整数除算は床を返すことになります。C にも C の一貫性があって、i % j が i と同じ符号を持つように i // j を丸めています。

i % j は、j が負の時には実際にはほとんど使いません。j が正なら、たくさん使います。その事実上すべての場合、i % j は >= 0 となる方が便利です。時計が 10 時を指している時、その 200 時間前は何時でしょうか。 -190 % 12 == 2 となるのが便利です。-190 % 12 == -10 は噛み付きかねないバグです。

ノート

Python 2 では、 __future__.division が有効でなければ、 a / b は a // b と同じ結果を返します。これは “古典的な (classic)” 除算とも呼ばれます。

文字列を数に変換するにはどうしたらいいですか?

整数に変換するには、組み込みの int() 型コンストラクタを使ってください。例えば、int('144') == 144 です。同様に、float() は浮動小数点に変換します。例えば、float('144') == 144.0 です。

デフォルトでは、これらは数を十進数として解釈するので、int('0o144') や int('0x144') は ValueError を送出します。int(string, base) はオプションの第二引数をとって変換元の基数にします。つまり int('0x144', 16) == 324 です。基数が 0 と指定された場合、その数は Python の基準によって解釈されます。先頭が ‘0o’ なら 八進数で、‘0x’ なら十六進数を表します。

文字列を数に変換するだけのために eval() を使わないでください。 eval() は特に遅いですし、セキュリティ上のリスクもあります。求められない副作用を持つような Python の式を渡そうとする人がいるかも知れません。例えば、あなたのホームディレクトリを消去する __import__('os').system("rm -rf $HOME") を渡そうとする人がいるかも知れません。

eval() にも数を Python の式として解釈する機能があります。だから例えば、eval('09') は構文エラー起こします。Python は ‘0’ で始まる数を八進数 (基数 8) とみなすからです。

数を文字列に変換するにはどうしたらいいですか?

例えば、144 という数を ‘144’ という文字列に変換したいなら、組み込みの型コンストラクタ str() を使ってください。十六進数や八進数にしたければ、組み込み関数の hex() や oct() を使ってください。装飾された形式にするには、書式指定文字列の文法 の項を参照してください。例えば、 "{:04d}".format(144) は '0144' になり、"{:.3f}".format(1/3) は '0.333' になります。文字列に % 演算子 を使うこともできます。詳細はライブラリリファレンスの解説を参照してください。

文字列をインプレースに変更するにはどうしたらいいですか?

文字列はイミュータブルなので、変更することはできません。それができるオブジェクトを作るには、その文字列をリストに変換してみるか、array モジュールを使ってください:

>>> s = "Hello, world"
>>> a = list(s)
>>> print a
['H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd']
>>> a[7:] = list("there!")
>>> ''.join(a)
'Hello, there!'

>>> import array
>>> a = array.array('c', s)
>>> print a
array('c', 'Hello, world')
>>> a[0] = 'y' ; print a
array('c', 'yello world')
>>> a.tostring()
'yello, world'

関数やメソッドを呼ぶのに文字列を使うにはどうしたらいいですか?

様々なテクニックがあります。

  • 一番いいのは、文字列を関数に対応させる辞書を使うことです。このテクニックの一番の利点は、文字列が関数の名前と同じ必要がないことです。この方法は case 構造をエミュレートするための一番のテクニックでもあります:

    def a():
        pass
    
    def b():
        pass
    
    dispatch = {'go': a, 'stop': b}  # Note lack of parens for funcs
    
    dispatch[get_input()]()  # Note trailing parens to call function
    
  • 組み込み関数の getattr() を使う方法:

    import foo
    getattr(foo, 'bar')()
    

    なお、getattr() はクラス、クラスインスタンス、モジュールなど、どんなオブジェクトにも使えます。

    これは標準ライブラリでも何箇所か使われています。このように:

    class Foo:
        def do_foo(self):
            ...
    
        def do_bar(self):
            ...
    
    f = getattr(foo_instance, 'do_' + opname)
    f()
    
  • locals() や eval() を使って関数名を決める方法:

    def myFunc():
        print("hello")
    
    fname = "myFunc"
    
    f = locals()[fname]
    f()
    
    f = eval(fname)
    f()
    

    ノート: eval() の使用は遅いし危険です。もしあなたが文字列の内容を絶対的に支配できなければ、任意の関数を実行されるようにする文字列を渡す人がいるかも知れません。

文字列から後端の改行を取り除く Perl の chomp() に相当するものはありますか?

Python 2.2 から、S.rstrip("\r\n") を使って文字列 S の終端から他の空白文字を取り除くことなくすべての行末記号を取り除くことができるようになりました。文字列 S が複数行を表し、終端に空行があるとき、そのすべての空行も取り除かれます:

>>> lines = ("line 1 \r\n"
...          "\r\n"
...          "\r\n")
>>> lines.rstrip("\n\r")
'line 1 '

これは典型的に一度に一行ずつテキストを読みたい時にのみ使われるので、 S.rstrip() をこの方法で使うとうまくいきます。

古いバージョンの Python では、部分的な代用品が二つあります:

  • すべての終端の空白文字を取り除きたいなら、文字列オブジェクトの rstrip() メソッドを使ってください。これは改行記号一つだけでなく、すべての終端の空白文字を取り除きます。
  • そうでなく、文字列 S に一行しか無いなら、S.splitlines()[0] を使ってください。

scanf() や sscanf() と同等なものはありますか?

そのようなものはありません。

簡単な入力解析で、多くの場合に一番簡単な方法は、文字列オブジェクトの split() メソッドで行を空白文字で区切られた単語に分け、十進数の文字列を int() や float() で数値に変換することです。 split() にはオプションの “sep” 変数があり、行に空白文字以外の区切りを使っているときに便利です。

もっと複雑な入力解析をしたいなら、C の sscanf() よりも正規表現の方が便利ですし、この処理に向いています。

‘UnicodeError: ASCII [decoding,encoding] error: ordinal not in range(128)’ とはどういう意味ですか?

このエラーは、あなたの Python インストールが 7-bit ASCII 文字列しか扱えないことを表します。この問題を扱うには二つの方法があります。

あなたのプログラムが、任意の文字セットエンコーディングのデータを扱わなければならないなら、一般に、アプリケーションが起動する環境によってデータのエンコーディングが特定されます。例えば、email や web 入力を扱うプログラムは、概して文字セットエンコーディング情報を Content-Type ヘッダから見つけます。これに使うことで、入力データを Unicode に正しく変換できます。 value によって参照される文字列が UTF-8 でエンコードされているとすれば:

value = unicode(value, "utf-8")

は Unicode オブジェクトを返します。データが UTF-8 に正しく変換されないなら、上記の呼び出しは UnicodeError 例外を送出します。

非 ASCII データを持つ文字列だけを Unicode に変換すればいいなら、まず ASCII エンコーディングを仮定して変換し、失敗したら Unicode オブジェクトを生成すればいいです:

try:
    x = unicode(value, "ascii")
except UnicodeError:
    value = unicode(value, "utf-8")
else:
    # value was valid ASCII data
    pass

デフォルトのエンコーディングは、Python ライブラリの一部である sitecustomize.py と呼ばれるファイルで設定できます。しかし、Python 全体におけるデフォルトのエンコーディングを変えてしまうことは、サードパーティ拡張モジュールの失敗につながるのでお勧めできません。

なお、Windows には、 “mbcs” として知られるエンコーディングがあり、これはあなたのロケールに依存するエンコーディイングを使います。多くの場合、特に COM で作業をするとき、これが使うのに適したデフォルトのエンコーディングです。

シーケンス(タプル/リスト)

タプル、リスト間の変更はどのようにするのですか?

型コンストラクタ tuple(seq) はすべてのシーケンス (実際には、すべてのイテラブル) を同じ要素、同じ順序のタプルに変換します。

例えば、 tuple([1, 2, 3]) は (1, 2, 3) を与え、tuple('abc') は ('a', 'b', 'c') を与えます。引数がタプルなら、コピーを作らずに引数のオブジェクトそのものを返すので、あるオブジェクトが既にタプルになっているか確信が持てないのなら、tuple() を呼ぶのが手軽です。

型コンストラクタ list(seq) はすべてのシーケンスあるいはイテラブルを同じ要素、同じ順序のリストに変換します。例えば、list(''''(1, 2, 3)) は [1, 2, 3] を与え、 list('abc') は ['a', 'b', 'c'] を与えます。引数がリストなら、seq[:] と同様にコピーを作ります。

インデクスが負の場合はどうなりますか?

Python のシーケンスは正の数と負の数でインデクスされます。正の数では、 0 が最初のインデクス、 1 が 2 番目のインデクス、以下も同様です。負のインデクスでは、-1 が最後のインデクス、 -2 が最後から 2 番目のインデクス、以下も同様です。seq[-n] は seq[len(seq)-n] と同じだと考えてください。

負のインデクスを使うと便利なことがあります。例えば、S[:-1] は文字列の最後以外のすべての文字を表すので、文字列の末尾の改行を取り除くときに便利です。

シーケンスを逆順にイテレートするにはどうしたらいいですか?

Python 2.4 で追加された reversed() を使ってください:

for x in reversed(sequence):
    ... # do something with x...

これは元のシーケンスをいじるのではなく、逆順の新しいコピーを作ってイテレートさせます。

Python 2.3 では、拡張スライス構文を使います:

for x in sequence[::-1]:
    ... # do something with x...

リストから重複を取り除くにはどうしますか?

Python Cookbook の長い議論に多くの方法があるので参照してください:

リストを並び替えて構わないのなら、ソートした上でリストの最初から最後までを調べ、次のように重複を削除してください:

if mylist:
    mylist.sort()
    last = mylist[-1]
    for i in range(len(mylist)-2, -1, -1):
        if last == mylist[i]:
            del mylist[i]
        else:
            last = mylist[i]

リストのすべての要素が辞書のキーとして使える (つまり、すべての要素がハッシュ可能) なら、おそらくこのほうが速いです:

d = {}
for x in mylist:
    d[x] = 1
mylist = list(d.keys())

Python 2.5 以降なら、代わりに次のようにできます:

mylist = list(set(mylist))

リストを集合に変換するときに重複は取り除かれるので、それをリストに戻せばいいのです。

Python で配列を作るにはどうしますか?

リストを使ってください:

["this", 1, "is", "an", "array"]

リストの時間計算量は C や Pascal の配列と同じです。大きな違いは、 Python のリストは多くの異なる型のオブジェクトを含めることです。

array モジュールにも固定された型を簡潔に表現する配列を作るためのメソッドがありますが、リストよりもインデクスが遅いです。また、 Numeric 拡張その他でも、様々な特徴をもつ配列的な構造体が定義されています。

Lisp 方式の連結リストを得るのに、タプルを使ってコンスセルをエミュレートできます:

lisp_list = ("like",  ("this",  ("example", None) ) )

ミュータブルな必要があるなら、タプルではなくリストを使いましょう。lisp の car にあたるものが lisp_list[0] で、cdr にあたるものが lisp_list[1] です。本当に必要だと確信できるとき以外はこれはしないでください。たいてい、これは Python のリストを使うよりも非常に遅いですから。

多次元のリストを作るにはどうしますか?

このようにして多次元の配列を作ろうとしてしまったことがあるでしょう:

A = [[None] * 2] * 3

これを表示したときには問題なさそうに見えます:

>>> A
[[None, None], [None, None], [None, None]]

しかし値を代入すると、その値が複数の場所に現れてしまいます:

>>> A[0][0] = 5
>>> A
[[5, None], [5, None], [5, None]]

これは、* を使ったリストの複製がコピーを作らず、存在するオブジェクトへの参照を作るだけだからです。この *3 は長さ 2 の同じリストへの参照を含むリストを作ります。一つの列に対する変更はすべての列に現れますが、これが望んだ結果であることはまずないでしょう。

おすすめの方法は、最初に望んだ長さのリストを作り、それから新しく作ったリストでそれぞれの要素を埋めていくことです:

A = [None] * 3
for i in range(3):
    A[i] = [None] * 2

これは長さ 2 の異なるリスト 3 つを含むリストを生成します。リスト内包表記も使えます:

w, h = 2, 3
A = [[None] * w for i in range(h)]

また、行列データ型を提供している拡張も使えます。Numeric Python が特に有名です。

オブジェクトのシーケンスにメソッドを適用するにはどうしますか?

リスト内包表記を使ってください:

result = [obj.method() for obj in mylist]

より一般的には、以下の関数を試すことができます:

def method_map(objects, method, arguments):
    """method_map([a,b], "meth", (1,2)) gives [a.meth(1,2), b.meth(1,2)]"""
    nobjects = len(objects)
    methods = map(getattr, objects, [method]*nobjects)
    return map(apply, methods, [arguments]*nobjects)

辞書

キーを安定した順序で表示する辞書を作るにはどうしたらいいですか?

できません。辞書はキーを予測できない順序で保存しているので、辞書の要素が表示される順序もまた予測できないのです。

ファイルに印字可能なバージョンを保存し、変更を加えてから他の印字された辞書と比較したい時に苛立たしいかもしれません。この場合は、pprint モジュールで辞書を整形して表示してください。要素がキーでソートされて表されます。

もっと複雑な解決策は、dict のサブクラスとして SortedDict クラスを作り、それに予測可能な順序で自身を表示させることです。そのようなクラスの単純な実装の一つは:

class SortedDict(dict):
    def __repr__(self):
        keys = sorted(self.keys())
        result = ("{!r}: {!r}".format(k, self[k]) for k in keys)
        return "{{{}}}".format(", ".join(result))

    __str__ = __repr__

これは完璧な解法とは程遠いですが、多くの状況でうまく働くでしょう。最大の欠点は、辞書のある値がまた辞書であった場合に、それらの値はどんな特定の順序でも表示されないことです。

複雑なソートがしたいのですが、Python でシュワルツ変換はできますか?

Perl コミュニティの Randal Schwartz の作とされるこのテクニックは、リストの要素を、それぞれの要素をその「ソート値」に対応付けるメトリックによってソートします。Python では、単に sort() メソッドに key 引数を使ってください:

Isorted = L[:]
Isorted.sort(key=lambda s: int(s[10:15]))

key 引数はPython 2.4 で追加されたもので、古いバージョンでこのようなソートをするにはリスト内包表記でやればすごく簡単です。文字列のリストをその大文字の値でソートするには:

tmp1 = [(x.upper(), x) for x in L]  # Schwartzian transform
tmp1.sort()
Usorted = [x[1] for x in tmp1]

それぞれの文字列の 10-15 の場所から展開されたサブフィールドの整数値によってソートするには:

tmp2 = [(int(s[10:15]), s) for s in L]  # Schwartzian transform
tmp2.sort()
Isorted = [x[1] for x in tmp2]

なお、Isorted はこのようにしても計算されます:

def intfield(s):
    return int(s[10:15])

def Icmp(s1, s2):
    return cmp(intfield(s1), intfield(s2))

Isorted = L[:]
Isorted.sort(Icmp)

しかし、このメソッドは intfield() を L の要素ごとに何度も呼び出すので、シュワルツ変換よりも遅いです。

リストを別のリストの値によってソートするにはどうしますか?

二つのリストを混ぜあわせてタプルのイテレータにしてから、必要な要素を選んでください:

>>> list1 = ["what", "I'm", "sorting", "by"]
>>> list2 = ["something", "else", "to", "sort"]
>>> pairs = zip(list1, list2)
>>> pairs = sorted(pairs)
>>> pairs
[("I'm", 'else'), ('by', 'sort'), ('sorting', 'to'), ('what', 'something')]
>>> result = [x[1] for x in pairs]
>>> result
['else', 'sort', 'to', 'something']

最後の段階の別のやり方は:

>>> result = []
>>> for p in pairs: result.append(p[1])

これのほうが読みやすいと、最後のリスト内包表記ではなくこれを使いたくなるかもしれません。しかし、これは長いリストではほぼ二倍の時間がかかります。なぜでしょうか。まず、append() 演算はメモリを割り当て直す必要があり、それを避けるために毎回ちょっと工夫していますが、それでも避けられないことがあるので、少し時間がかかるのです。二つ目に、”result.append” には属性探索が余計に必要で、三つ目に、これらすべての関数を呼ぶ必要があることで速度が落ちてしまいます。

オブジェクト

クラスとは何ですか?

クラスは、class 文の実行で生成される特殊なオブジェクトです。クラスオブジェクトはインスタンスオブジェクトを生成するためのテンプレートとして使われ、あるデータ型に特有のデータ (attribute/属性) とコード (メソッド) の両方を内蔵しています。

新しいクラスを一つ以上の他のクラス (新しいクラスの基底クラスと呼ばれます) に基づいて作ることもできます。この新しいクラスは、基底クラスから属性とメソッドを継承します。これにより、オブジェクトモデルを継承で連続的に洗練できます。メールボックスへの基本的なアクセサを提供する一般的な Mailbox クラスを作って、それからいろいろな特定のメールボックスの形式を扱う MboxMailbox、 MaildirMailbox、OutlookMailbox のようなサブクラスを作れるのです。

メソッドとは何ですか?

メソッドは、オブジェクト x が持つ関数で、通常 x.name(arguments...) として呼び出されるものです。メソッドはクラス定義の中で関数として定義されます:

class C:
    def meth (self, arg):
        return arg * 2 + self.attribute

self とは何ですか?

self はメソッドの第一引数に慣習的につけられる名前にすぎません。 meth(self, a, b, c) として定義されたメソッドは、その定義がなされたクラスのインスタンス x に対して x.meth(a, b, c) として呼び出されます。呼び出されたメソッドは、meth(x, a, b, c) が呼ばれたものと考えます。

なぜメソッドの定義や呼び出しにおいて ‘self’ を明示しなければならないのですか? も参照してください。

あるオブジェクトが、与えられたクラスやそのサブクラスのインスタンスであるかを調べるにはどうしますか?

ビルトイン関数 isinstance(obj, cls) を使ってください。クラスのタプルを与えて isinstance(obj, (class1, class2, ...)) のようにすれば、あるオブジェクトが任意の数のクラスのオブジェクトであるかを調べられますし、 isinstance(obj, str) や isinstance(obj, (int, long, float, complex)) のようにすれば、Python のビルトイン型のオブジェクトであるかも調べられます。

なお、大部分のプログラムでは、isinstance() をユーザー定義のクラスに何度も使うべきではありません。クラスを自分で開発するときに、適切なオブジェクト指向スタイルは、特定の振る舞いをカプセル化するクラスのメソッドを定義するものであって、オブジェクトのクラスを調べてそのクラスに応じて違うことをするものではありません。例えば、何かをする関数があったとして:

def search(obj):
    if isinstance(obj, Mailbox):
        # ... code to search a mailbox
    elif isinstance(obj, Document):
        # ... code to search a document
    elif ...

よりよいアプローチは、search() メソッドをすべてのクラスに定義して、それをただ呼び出すことです:

class Mailbox:
    def search(self):
        # ... code to search a mailbox

class Document:
    def search(self):
        # ... code to search a document

obj.search()

委譲とは何ですか?

委譲 (delegation) とは、オブジェクト指向のテクニック (デザインパターンとも呼ばれる) の一つです。オブジェクト x があって、そのメソッドのうちただ一つの振る舞いを変えたいとしましょう。新しいクラスを作成し、変えたいメソッドだけを新しく実装し、他のすべてのメソッドを x の対応するメソッドに委譲する新しいクラスを作れます。

Python プログラマは簡単に委譲を実装できます。例えば、以下のクラスは、ファイルのように振る舞いながらすべての文字を大文字に変換するクラスを実装します:

class UpperOut:

    def __init__(self, outfile):
        self._outfile = outfile

    def write(self, s):
        self._outfile.write(s.upper())

    def __getattr__(self, name):
        return getattr(self._outfile, name)

ここで UpperOut クラスは write() メソッドを定義しなおして、引数の文字列を大文字に変換してから基礎となる self._outfile.write() メソッドを呼び出すようにします。その他すべてのメソッドは基礎となる self._outfile オブジェクトに移譲されます。この委譲は __getattr__ メソッドを通してなされます。属性の制御の詳細は 言語リファレンス を参照してください。

なお、一般的に委譲はトリッキーになりがちです。属性が設定される時には読み出される時と同様に、そのクラスに __setattr__() メソッドを定義する必要があり、それには細心の注意が必要です。 __setattr__() の基本的な実装はおおよそ以下のようになります:

class X:
    ...
    def __setattr__(self, name, value):
        self.__dict__[name] = value
    ...

たいてい、__setattr__() 実装は self.__dict__ を変更して、無限再帰を起こすことなくローカルな状態を保存するようにしなければなりません。

基底クラスで定義されたメソッドを、そのクラスをオーバーライドした派生クラスから呼び出すにはどうしますか?

組み込みの super() 関数を使ってください:

class Derived(Base):
    def meth (self):
        super(Derived, self).meth()

旧スタイルクラスを使っているなら: class Derived(Base): ... のようなクラス定義で、 Base.meth(self, arguments...) とすれば、Base (または Base の基底クラス) で定義された meth() メソッドを呼び出せます。ここで、 Base.meth は束縛されていないメソッドなので、self 引数を渡す必要があります。

基底クラスの名前を変えやすいコードを書くにはどうしますか?

基底クラスのエイリアス (alias) を定義し、先にそれに本当の基底クラスを代入しておいてから、クラス定義の中でそのエイリアスを使うといいかもしれません。そうすればエイリアスに代入する値を変変えるだけで済みます。ちなみに、この手法は使用する基底クラスを動的に選びたいとき (使えるリソースに依るとき等) にも便利です。例:

BaseAlias = <real base class>

class Derived(BaseAlias):
    def meth(self):
        BaseAlias.meth(self)
        ...

静的なクラスデータや静的なクラスメソッドを作るにはどうしますか?

(C++ や Java の意味で) 静的なデータも静的なメソッドも Python でサポートされています。

静的なデータを作るには、単純にクラス属性を定義してください。その属性に新しい値を代入するには、代入するクラス名を明示する必要があります:

class C:
    count = 0   # number of times C.__init__ called

    def __init__(self):
        C.count = C.count + 1

    def getcount(self):
        return C.count  # or return self.count

c そのものや c.__class__ から C にいたるパス探索経路上のクラスによってオーバーライドされない限り、c.count も isinstance(c, C) であるすべての c に対する C.count を参照します。

注意: C のメソッド内では、 self.count = 42 のような代入は self 自身の辞書に “count” という名前の新しくて関係ないインスタンスを作ります。クラスの静的なデータの再束縛には、メソッド内であるか否かにかかわらず、いつもクラスを指定しなければなりません:

C.count = 314

静的メソッドは Python 2.2 以降で使えます:

class C:
    def static(arg1, arg2, arg3):
        # No 'self' parameter!
        ...
    static = staticmethod(static)

Python 2.4 のデコレータを使って、以下のようにも書けます:

class C:
    @staticmethod
    def static(arg1, arg2, arg3):
        # No 'self' parameter!
        ...

しかし、静的メソッドの効果を得るもっと簡単な方法は、単にモジュールレベル関数を使うことです:

def getcount():
    return C.count

モジュールあたりに一つのクラスを定義するように (あるいはクラス組織を厳密に関連させるように) コードが構成されているなら、これで必要なカプセル化ができます。

Python でコンストラクタ(やメソッド)をオーバーロードするにはどうしたらいいですか?

この質問の答えはすべてのメソッドについて言えることですが、この質問はだいたい以下の構造の文脈から出てきます。

C++ では、このように書けます:

class C {
    C() { cout << "No arguments\n"; }
    C(int i) { cout << "Argument is " << i << "\n"; }
}

Python では、一つのコンストラクタでデフォルトの引数を使ってすべての場合に対応するように書かなければなりません。例えば:

class C:
    def __init__(self, i=None):
        if i is None:
            print "No arguments"
        else:
            print "Argument is", i

これで完全に等価とは言えませんが、実用上は十分に近いです。

長さが変えられる引数のリストを試すには、例えば:

def __init__(self, *args):
    ...

これと同じやり方がすべてのメソッド定義で使えます。

__spam を使おうとしたら _SomeClassName__spam からエラーがでました。

先頭にアンダースコアが二つ付いた変数名は、クラスのプライベートな変数を、 “マングル化”という単純かつ効率のいい方法で定義します。__spam のような形式 (先頭に二つ以上、末尾にもしあっても一つのアンダースコアがある) のすべての識別子は、classname が先頭のアンダースコアをすべて削除した現在のクラス名とすれば、_classname__spam のように文字上で置換えられます。

これはプライベートであることを保証するものではありません。これでも外部のユーザが “_classname__spam” 属性に直接アクセスできますし、プライベートな変数はオブジェクトの __dict__ から見えます。多くの Python プログラマはわざわざプライベートな変数名を使おうとなど考えません。

クラスに __del__ メソッドを定義しているのですが、オブジェクトを削除したときに呼ばれません。

いくつかの可能性があります。

del 文は必ずしも __del__() を呼び出すとは限りません – これは単純にオブジェクトの参照カウントを減らすもので、カウントがゼロになったときに __del__() が呼び出されます。

データ構造が循環リンク (子のそれぞれが親の参照を持ち、親のそれぞれが子のリストを持つツリーなど) を含む場合、その参照カウントは決して 0 にはなりません。時々、Python はこのようなサイクルを検出するアルゴリズムを実行しますが、データ構造への参照がなくなってからこのガベージコレクタが実行されるまでいくらか時間が掛かるかもしれないので、 __del__() メソッドは不便な予測できないときに呼び出されるかもしれません。これは問題を再生しようとするときに不便です。さらに悪いことに、オブジェクトの __del__() メソッドが実行される順序は任意です。 gc.collect() を起動して収集を強制することができますが、オブジェクトが決して回収されないような本当に病的な場合も あります。

周期的なコレクタにかかわらず、オブジェクトに close() メソッドを明示的に定義し、使い終わったらいつでも呼び出せるようにするのはいいことです。そうすれば close() メソッドはサブオブジェクトへの参照をする属性を取り除いてくれます。__del__() を直接呼び出さないでください – __del__() は close() を呼び出すでしょうし、close() なら同じオブジェクトに対して複数回呼ばれてもいいことが保証されているでしょう。

循環参照を避ける他の方法は、 weakref モジュールを使って、参照カウントを増やすことなくオブジェクトを示すことです。例えばツリー構造は、親と (必要なら!) 兄弟に弱参照を使うべきです。

except 節で例外を捕まえた関数内でオブジェクトがローカル変数であったたなら、そのオブジェクトへの参照が関数のスタックフレーム内でスタックトレース内に含まれることで存在する可能性があります。通常、 sys.exc_clear() を呼び出せば、最後に記録された例外を消去することで対処してくれます。

最後に、__del__() メソッドが例外を発生させた場合、警告のメッセージが sys.stderr に書きこまれます。

与えられたクラスのすべてのインスタンスのリストを得るにはどうしますか?

Python はクラス (やビルトイン型) のすべてのインスタンスをたどりません。クラスのコンストラクタにそれぞれのインスタンスへの弱参照のリストを作らせることですべてのインスタンスをたどらせられます。

モジュール

.pyc ファイルを作るにはどうしますか?

モジュールが最初にインポートされるとき (またはソースが現在コンパイルされているファイルよりも新しいとき)、コンパイルされたコードを含む .pyc ファイルが .py ファイルと同じディレクトリに作られるでしょう。

.pyc ファイルが作られないとしたら、ディレクトリの許可の問題があるかもしれません。たとえばこれは、web サーバなどでテストするときのように、開発のときと違うユーザとして起動するときなどに起こりえます。モジュールをインポートしたときに Python がコンパイルされたモジュールをディレクトリに書き込むための条件 (許可、容量の空き、etc...) が揃っていれば、.pyc ファイルの生成は自動的に行われます。

トップレベルのスクリプトで Python を起動するときにはインポートは考慮されず、 .pyc は生成されません。例えば、トップレベルモジュール abc.py があって、他のモジュール xyz.py をインポートするようになっているとき、abc を起動すると、xyz のインポート時に xyz.pyc が生成されますが、abc.py はインポートされないので abc.pyc ファイルは生成されません。

abc.pyc が必要なら – つまり、インポートされないモジュールの .pic ファイルを生成するためには – py_compile や compileall モジュールが利用できます。

py_compile モジュールは手動で任意のモジュールをコンパイルできます。やり方の一つは、このモジュールの compile() 関数をインタラクティブに実行することです:

>>> import py_compile
>>> py_compile.compile('abc.py')

これで abc.py と同じロケーション(オプション変数の cfile で変更することもできます)に .pyc ファイルが書き込まれます。

compileall モジュールを使えば自動的に一つや複数のディレクトリのすべてのファイルをコンパイルできます。シェルプロンプトから compileall.py を起動して、コンパイルしたいファイルを含むディレクトリのパスを指定してください:

python -m compileall .

現在のモジュール名を知るにはどうしますか?

モジュールは前もって定義されたグローバル変数 __name__ を検索することで自身の名前を決定できます。この値が '__main__' であるとき、そのプログラムはスクリプトとして実行されています。インポートされることによって使われる大抵のモジュールはコマンドラインインタフェースや自己テストも提供していて、 __name__ をチェックしてからそのコードだけを実行します:

def main():
    print 'Running test...'
    ...

if __name__ == '__main__':
    main()

相互にインポートしあうモジュールを作るにはどうしたらいいですか?

以下のモジュールがあったとしましょう:

foo.py:

from bar import bar_var
foo_var = 1

bar.py:

from foo import foo_var
bar_var = 2

問題はインタプリタが以下の段階を実行することです:

  • main が foo をインポートする
  • foo の空のグローバルが生成される
  • foo がコンパイルされ実行を始める
  • foo が bar をインポートする
  • bar の空のグローバルが生成される
  • bar がコンパイルされ実行を始める
  • bar が foo をインポートする(すでに foo という名前のモジュールがあるので no-op となる)
  • bar.foo_var = foo.foo_var

この最後の段階は失敗します。Python が foo を解釈し終わっていなくて、 foo のグローバルなシンボルの辞書はまだ空ですから。

import foo を使って、グローバルコードの foo.foo_var にアクセスしようとしたときにも、これと同じことが起こります。

この問題には (少なくとも) 三つの解決策があります。

Guido van Rossum は from <module> import ... を全く使わないで、すべてのコードを関数の中に入れることを勧めています。グローバル変数とクラス変数の初期化は定数とビルトイン関数のみで行われるべきです。これでインポートされたすべてのモジュールは <module>.<name> として参照されることになります。

Jim Roskind はそれぞれのモジュールに対して以下の順に進めることを提案しています:

  • エクスポート (インポートされた基底クラスを必要としないグローバル、関数、クラス)
  • import 文
  • アクティブなコード (インポートされた値によって初期化されるグローバルを含む)

インポートが奇妙な場所に現れることから van Rossum はこの方法をそれほど好みませんが、これは有効です。

Matthias Urlichs は第一に再帰インポートが必要ないようにコードを構築しなおすことを推奨しています。

これらの解決策はそれぞれ両立させることもできます。

__import__(‘x.y.z’) は <module ‘x’> を返しますが、z を得るためにはどうしますか?

こうしてみてください:

__import__('x.y.z').y.z

もっと現実的には、こうするべきかもしれません:

m = __import__(s)
for i in s.split(".")[1:]:
    m = getattr(m, i)

import_module() という便利な関数があるので、 importlib を参照してください。

インポートされたモジュールを編集してから再インポートしましたが、変化が現れません。なぜですか?

効率と一貫性上の理由から、Python はモジュールが最初にインポートされた時にのみモジュールファイルを読み込みます。そうしないと、たくさんのモジュールでできていて、それぞれが同じ基本モジュールをインポートしているようなプログラムでは、その基本モジュールの解析と再解析が繰り返されることになります。変更されさたモジュールの再読込を強制するには、こうしてください:

import modname
reload(modname)

注意:この手法は 100%安全とは言えません。とりわけ:

from modname import some_objects

のような文を含むモジュールは、インポートされたオブジェクトの古いバージョンを使い続けます。そのモジュールにクラス定義が含まれていたら、存在するクラスインスタンスは新しいクラス定義を使うようにアップデート されません。これによって以下の矛盾した振舞いがなされえます:

>>> import cls
>>> c = cls.C()                # Create an instance of C
>>> reload(cls)
<module 'cls' from 'cls.pyc'>
>>> isinstance(c, cls.C)       # isinstance is false?!?
False

この問題の性質は、クラスオブジェクトを印字することで明らかになります:

>>> c.__class__
<class cls.C at 0x7352a0>
>>> cls.C
<class cls.C at 0x4198d0>