PythonにはC#のような拡張メソッドがありますか?次のようなメソッドを呼び出すことは可能ですか?
MyRandomMethod()
int
のような既存のタイプでは?
myInt.MyRandomMethod()
Pythonコード(別名モンキーパッチ)で定義されたクラスオブジェクトに好きなメソッドを追加できます。
>>> class A(object):
>>> pass
>>> def stuff(self):
>>> print self
>>> A.test = stuff
>>> A().test()
組み込み型では__dict__
が書き込み可能ではないため、これは機能しません(dictproxy
です)。
つまり、Pythonには「実際の」拡張メソッドメカニズムはありません。
それがあなたが求めているものかどうかはわかりませんが、既存のタイプを拡張してから、新しいもので好きなように呼び出すことができます:
class int(int):
def random_method(self):
return 4 # guaranteed to be random
v = int(5) # you'll have to instantiate all you variables like this
v.random_method()
class int(int):
def xkcd(self):
import antigravity
print(42)
>>>v.xkcd()
Traceback (most recent call last):
File "<pyshell#81>", line 1, in <module>
v.xkcd()
AttributeError: 'int' object has no attribute 'xkcd'
c = int(1)
>>> c.random_method()
4
>>> c.xkcd()
42
それがあなたの質問を明確にすることを願っています
Forbidden Fruitで実行できます( https://pypi.python.org/pypi/forbiddenfruit )
Forbiddenfruitをインストールします。
pip install forbiddenfruit
次に、組み込みタイプを拡張できます。
>>> from forbiddenfruit import curse
>>> def percent(self, delta):
... return self * (1 + delta / 100)
>>> curse(float, 'percent', percent)
>>> 1.0.percent(5)
1.05
ForbiddenFruitは基本的にCAPIに依存しており、cpython実装でのみ機能し、Jython、pypyなどの他のpython実装では機能しません。
私はここで説明されている方法で幸運に恵まれました:
http://mail.python.org/pipermail/python-dev/2008-January/076194.html
ビルトインで動作するかどうかはわかりませんが。
次の context manager は、ForbiddenFruitのようなメソッドを制限なしで追加します。それに加えて、後で拡張メソッドを削除するという追加の利点があります。
class extension_method:
def __init__(self, obj, method):
method_name = method.__name__
setattr(obj, method_name, method)
self.obj = obj
self.method_name = method_name
def __enter__(self):
return self.obj
def __exit__(self, type, value, traceback):
# remove this if you want to keep the extension method after context exit
delattr(self.obj, self.method_name)
使用法は次のとおりです。
class C:
pass
def get_class_name(self):
return self.__class__.__name__
with extension_method(C, get_class_name):
assert hasattr(C, 'get_class_name') # the method is added to C
c = C()
print(c.get_class_name()) # prints 'C'
assert not hasattr(C, 'get_class_name') # the method is gone from C
別のオプションは、メタクラスをオーバーライドすることです。これにより、特に、すべてのクラスに存在する必要のある関数を指定できます。
この記事はそれについて議論し始めます:
http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html