2014/08/01

Python Tips:既存のクラスにインスタンスメソッドを追加したい

Pythonで、既存のクラスにインスタンスメソッドを追加する方法をご紹介します。

既存のクラスにメソッドを追加するには次の手順を踏みます。
まず関数を別途定義してから
その関数名をクラスのアトリビュートにする

具体例を見てみます。
# __init__ メソッドだけを備えた Dog クラス
class Dog(object):
    def __init__(self, name):
        self.name = name

# 以下で Dog クラスに count_number というインスタンスメソッドを追加する
# 01 まずは関数を定義
def count_number(self):
    print "%s counts: one! one!" % self.name

# 02 定義した関数をクラスのアトリビュートに追加
Dog.count_number = count_number

# 結果
taro = Dog("Taro")
taro.count_number()  # => Taro counts: one! one!
# count_number がインスタンスメソッドとして機能している

最初に Dog クラスを定義したときには存在しなかった count_number というメソッドが、最後にはインスタンスをレシーバとして呼び出せていることがわかります。

定義した関数をクラスのアトリビュートに追加するところは、そのままずばりな setattr という関数を使って書くことも可能です。
setattr(Dog, "count_number", count_number)

関数名をそのままメソッド名にしてもよい場合は、次のように関数化しておくと繰り返しが避けられます。
# 既存のクラスにインスタンスメソッドを追加する関数
def add_instance_method(Klass, method):
    setattr(Klass, method.__name__, method)  # method.__name__ は関数名を表す


このようなふるまいを見ると、「Pythonにおいてインスタンスメソッドというのはレシーバ自身が第一引数に渡されるクラスメソッドにすぎない」ということがよくわかります。

ちなみに、Rubyのように組み込みの型(クラス)にメソッドを追加するということはPythonではできません。このあたりは、どこを重視するかの考え方のちがい、でしょうか。

以上です。


参考
Python - cool things I've discovered
python - Adding a Method to an Existing Object - Stack Overflow

0 件のコメント: