技術情報棚卸し(平日限定)

todoa2cの技術情報棚卸しです。平日限定ってことはアレだ。言わせんな恥ずかしい。

Pythonのインスタンスメソッドと関数実行

3.データモデルのうち「インスタンスメソッド」を読んでいたのですが、興味深い一文を見つけました。

インスタンスメソッドオブジェクトが呼び出される際、根底にある関数 (func) が呼び出されます。このとき、クラスインスタンス (self) が引数リストの先頭に挿入されます。例えば、 C を関数 f() の定義を含むクラス、 x を C のインスタンスとすると、 x.f(1) の呼び出しは C.f(x, 1) の呼び出しと同じです。

これを使うと、あるクラスのインスタンスメソッドを列挙しておいて、 リフレクションのように順次メソッドを実行しておくことが簡単に、かつオーバーヘッドがない状態で 実行することができる模様です。

こういう具合に書くと、

1
2
3
4
5
6
ops = [Puzzle.up, Puzzle.down]

p = Puzzle()

for op in ops:
    op(p)

こういう書き方をしたときと同じ挙動になるわけです。

1
2
3
p = Puzzle()
p.up()
p.down()

行数は後者の方が少ないですが、前者の書き方が必要なときもあるんですよ。 特にメソッドをひたすら実行しまくる場合には、前者の書き方は便利です。 しかもJavaでリフレクションを使った時のようなオーバーヘッドがないのは良いですね (普通Javaではこういう書き方せずにインターフェースとか使うけど)。

クラスでメソッド定義をするときに、def up(self): と書くのは、 インスタンスメソッドとして使った場合には、第1引数のselfにはオブジェクトそのものを勝手に 指定してくれるような動きになっているのかな?

追記 (2014-03-19)

メソッドはレシーバを第1引数に受け取るただの関数、ということだそうです。

Comments