そうだ! EuroPython 2011へ行こう

#2 CPythonについてのハンズオン,講演

この記事を読むのに必要な時間:およそ 12 分

Pythonのsuper()ができること

super新スタイルクラス(Python3ではデフォルト)でのみ使える機能で,親または兄弟クラスのメソッドを呼び出すプロキシオブジェクトを返します。superを使って委譲することで,サブクラスにてデフォルトの移譲先を変更できます。

>>> from collections import Counter, OrderedDict
>>> class OrderedCounter(Counter, OrderedDict):
...     pass

>>> OrderedCounter('abracadabra')
OrderedCounter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})

画像

このサンプルは,CounterOrderedDictを継承してOrderedCounterを定義します。Counterdictのサブクラスで,その__init__()update()メソッドの中でsuperを使ってその処理を委譲します。CounterOrderedDictの実装の一部が次になります。

class Counter(dict):
  def __init__(self, iterable=None, **kwds):
    super(Counter, self).__init__()
    self.update(iterable, **kwds)

  def update(self, iterable=None, **kwds):
    ...
    super(Counter, self).update(iterable)
    ...
class OrderedDict(dict):
  def __init__(self, *args, **kwds):
    ...
    self.__update(*args, **kwds)

  update = MutableMapping.update
  __update = update # let subclasses override update without breaking __init__

新スタイルクラスのメソッド解決順序(MRO)__mro__で調べられます。

>>> OrderedCounter.__mro__
(<class '__main__.OrderedCounter'>,
 <class 'collections.Counter'>,
 <class 'collections.OrderedDict'>,
 <type 'dict'>,
 <type 'object'>)

メソッドを調べる順番がOrderedCounter -> Counter -> OrderedDictの順番であるのが分かります。

実際の呼び出しは次のようになります。Counter.__init__内にsuperの呼び出しがあるのでOrdereedDict.__init__()が呼ばれます。その次にself.update()(Counter.update)メソッド内でもsuperの呼び出しがあるのでOrdereedDict.update()が呼ばれます。

説明が前後してしまいますが,Counterのメソッド解決順序(MRO)を調べると,Counter -> dictであることが分かります。

>>> Counter.__mro__
(<class 'collections.Counter'>,
 <type 'dict'>,
 <type 'object'>)

つまりCounter__init__()メソッドとupdate()メソッド内のsuperの移譲先が,OrderedCounter(Counter,OrderedDict)を定義したことにより,dictからOrderedCounterに変更されたことが分かります。

Tip
Python3ではsuperを引数なしで呼び出せます。その際は,第1引数に現在のクラスが,第2引数に現在のメソッドの第1引数が使われます。例えば,このCounterのサンプルの場合,super(Counter,self).__init__()super().__init__()は同じです。

詳細に興味がある方はPython⁠s super() considered super!とそこで紹介されているサンプルコードHow to use super() effectively – Python 2.7 versionを参照してください。

次回#3 PyPyについての講演,ハンズオン,スプリントに続きます。

著者プロフィール

森本哲也(もりもとてつや)

一介のプログラマ。

自分で設計して,自分で開発して,自分で直せるような独立したプログラマを目指している。OSSコミュニティのゆるい人のつながりが性にあっていてPythonプログラミングが好き。共訳書に『エキスパート Pythonプログラミング』(アスキーメディアワークス)がある。

Twitter:@t2y

ブログ:http://d.hatena.ne.jp/t2y-1979/