パスワードを忘れた? アカウント作成
12525819 journal
日記

jordan_bethの日記: python getattr で取得したメソッドの呼び出し 1

日記 by jordan_beth

インスタンスのメソッドを動的に呼び出す必要があったので、getattr で取得し、そこメソッドを実行するコードを書いていてハマる。

class Test(object) :
        def __init__(self, multiplier) :
                self.multiplier = multiplier
        def calc(self, a, b) :
                print(self.multiplier * (a + b))

というクラスがあったとして、

>>> var = Test(10)
>>> func = getattr(var, 'calc')
>>> func(var, 2, 4)
Traceback (most recent call last):
    File "", line 1, in
TypeError: calc() takes exactly 3 arguments (4 given)

で引数が多いと怒られる。

>>> func(2, 4)
60

ということで、インスタンスで getattr したメソッドでは、その呼出においてインスタンスオブジェクトの引き渡しは必要ないようだ。バインド済みだからってこと?

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • by Anonymous Coward on 2015年09月25日 20時10分 (#2888959)
    Pythonのメソッドは普通の関数とは異なるクラス(instancemethodクラス)であり、クラスで定義された関数はメソッドになります。
    メソッドは操作対象を属性として持っているのでインスタンスから得たメソッドは束縛しなおす必要がありません。
    @staticmethodを使って定義したメソッドは普通の関数と同じです。
    メソッドが持っている操作対象のインスタンスはmethod.__self__で取得できます。

    >>> class C:
    ...   def a(self): pass
    ...   @staticmethod
    ...   def b(): pass
    ...
    >>> C.a
    <unbound method C.a>
    >>> C.b
    <function b at 0x00DA5EF0>
    >>> c = C()
    >>> c.a
    <bound method C.a of <__main__.C instance at 0x00DAC508>>
    >>> c.b
    <function b at 0x00DA5EF0>
    >>> c.a.__self__ is c
    True

    なおmethod.__self__は読み取り専用なので後で束縛を変更したい場合はmethod.__func__で束縛される前の関数(未束縛のメソッドではない)が取得できます。
    普通の関数をメソッドにするにはnew.instancemethod関数を使います。
    詳しくは言語リファレンスの3.2.標準型の階層の呼び出し可能型の項を参照して下さい。
typodupeerror

皆さんもソースを読むときに、行と行の間を読むような気持ちで見てほしい -- あるハッカー

読み込み中...