Python で既存のオブジェクト (つまり、クラス定義内ではないオブジェクト) にメソッドを追加するにはどうすればよいですか?
一部の例外を除いて、そうすることは一般的に良い方法とは見なされていないことを理解しています。
ベストアンサー1
Python では、関数とバインドされたメソッドには違いがあります。
>>> def foo():
... print "foo"
...
>>> class A:
... def bar( self ):
... print "bar"
...
>>> a = A()
>>> foo
<function foo at 0x00A98D70>
>>> a.bar
<bound method A.bar of <__main__.A instance at 0x00A9BC88>>
>>>
バインドされたメソッドはインスタンスに「バインド」されており (説明の仕方)、メソッドが呼び出されるたびにそのインスタンスが最初の引数として渡されます。
ただし、クラスの属性 (インスタンスではなく) である呼び出し可能オブジェクトはバインドされていないため、必要に応じていつでもクラス定義を変更できます。
>>> def fooFighters( self ):
... print "fooFighters"
...
>>> A.fooFighters = fooFighters
>>> a2 = A()
>>> a2.fooFighters
<bound method A.fooFighters of <__main__.A instance at 0x00A9BEB8>>
>>> a2.fooFighters()
fooFighters
以前に定義されたインスタンスも更新されます (それ自体が属性をオーバーライドしていない限り)。
>>> a.fooFighters()
fooFighters
問題は、メソッドを単一のインスタンスにアタッチする場合に発生します。
>>> def barFighters( self ):
... print "barFighters"
...
>>> a.barFighters = barFighters
>>> a.barFighters()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: barFighters() takes exactly 1 argument (0 given)
関数はインスタンスに直接アタッチされている場合、自動的にバインドされません。
>>> a.barFighters
<function barFighters at 0x00A98EF0>
それをバインドするには、タイプモジュールのMethodType関数:
>>> import types
>>> a.barFighters = types.MethodType( barFighters, a )
>>> a.barFighters
<bound method ?.barFighters of <__main__.A instance at 0x00A9BC88>>
>>> a.barFighters()
barFighters
今回はクラスの他のインスタンスは影響を受けません。
>>> a2.barFighters()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: A instance has no attribute 'barFighters'