PythonのRubyのmethod_missing
メソッドと同等のものは何ですか?私は__getattr__
を使ってみましたが、このフックもフィールドに適用されます。私はメソッドの呼び出しをインターセプトしたいだけです。それを行うPythonの方法は何ですか?Rubyの 'method_missing'に相当するPython
答えて
プロパティとメソッドの間にPythonの違いはありません。メソッドは型がちょうどinstancemethod
の単なるプロパティです。このメソッドは呼び出し可能です(__call__
をサポートしています)。
__getattr__
メソッドを実装したい場合は、関数を返してください(lambda
または普通のdef
)。コール後に何かをチェックしてください。
PythonはRubyのやり方とは異なり、メソッドと属性(「インスタンス変数」など)を区別しません。メソッドやその他のオブジェクト属性は、Pythonで全く同じ方法で検索されます。Pythonでさえルックアップ段階での違いを知るわけではありません。属性が見つかるまで、それは単なる文字列です。
あなたは__getattr__
のみは、メソッドのためと呼ばれていることを確認する方法を求めているのであれば、私はあなたがおそらくエレガントな解決策を見つけることができません怖いです。しかし、__getattr__
から関数(またはまったく新しいdynamically bound method)を返すだけで十分です。
をRubyでは 'method_missing'を、スモールトークでは' doesNotUnderstand'を使います。 – missingfaktor
私はなぜあなたが '__getattr__'を使いたいのか理解しています。私はあなたがなぜメソッド呼び出しを傍受したいのか理解できません。 – senderle
私の設計ではフィールドへのアクセスを傍受する必要はありませんでしたが、大きな障害とは思われません。私は@Emilによって提供される解決策が私の要求に十分に適していることを知ります。 – missingfaktor
私はそれをお勧めしませんが!!!!!!!!!!!!!!!!!!!!!
このようなことは、呼び出し可能な属性/メソッドに対応しないすべての名前に対して特別なメソッドを呼び出す動作に近づくことになります。もちろん、彼らはまだ本当に別の名前空間を持っていないので、少し奇妙に感じるかもしれません。それはより低いレベルで動作する__getattribute__
をオーバーライドして動作します。__getattr__
それが失敗した場合は属性を取得しようとします。コールされた特殊メソッドを返します。成功した場合は呼び出し可能な場合はそれを渡します。 は、特殊メソッドで呼び出しを実装する点を除いて、ほぼ同じように動作するプロキシオブジェクトで結果をラップします。
呼び出し元のオブジェクトにアクセスすることはできません。呼び出し元のオブジェクトにアクセスすることは許可されていません。私が考えることができると思うのは、1分後にそれを削除する新しいスレッドを開始することです。その場合、サポートされていないクロージャでそれを使用していない限りおそらく呼び出されます)。
編集:私は忘れてしまったコール可能ないくつかの偽陽性があるかもしれません。
は http://pypi.python.org/pypi/ProxyTypesライブラリに依存from peak.util.proxies import ObjectWrapper
from functools import partial
def m(name, *args, **kwargs):
print(name,repr(args),repr(kwargs))
class CallProxy(ObjectWrapper):
def __init__(self, obj, m, method_name):
ObjectWrapper.__init__(self, obj)
object.__setattr__(self, "_method_name", method_name)
object.__setattr__(self, "_m", m)
def __call__(self, *args, **kwargs):
return self._m(self._method_name, *args,**kwargs)
class Y(object):
def __init__(self):
self.x = [3]
def __getattribute__(self, name):
try:
val = object.__getattribute__(self, name)
if not callable(val):
return CallProxy(val, m, name)
else:
return val
except AttributeError:
return partial(m, name)
In [2]: y=Y()
In [3]: y.x
Out[3]: [3]
In [4]: y.z
Out[4]: <functools.partial at 0x2667890>
In [5]: y.zz([12])
('zz', '([12],)', '{}')
In [6]: y.x.append(5)
In [7]: y.x
Out[7]: [3, 5]
In [8]: y.x(1,2,3,key="no")
('x', '(2, 3)', "{'key': 'no'}")
あなたは以下の方法で機能のようなmissing_method実装することができ
:同じ理由
https://gist.github.com/gterzian/6400170
import unittest
from functools import partial
class MethodMissing:
def method_missing(self, name, *args, **kwargs):
'''please implement'''
raise NotImplementedError('please implement a "method_missing" method')
def __getattr__(self, name):
return partial(self.method_missing, name)
class Wrapper(object, MethodMissing):
def __init__(self, item):
self.item = item
def method_missing(self, name, *args, **kwargs):
if name in dir(self.item):
method = getattr(self.item, name)
if callable(method):
return method(*args, **kwargs)
else:
raise AttributeError(' %s has not method named "%s" ' % (self.item, name))
class Item(object):
def __init__(self, name):
self.name = name
def test(self, string):
return string + ' was passed on'
class EmptyWrapper(object, MethodMissing):
'''not implementing a missing_method'''
pass
class TestWrapper(unittest.TestCase):
def setUp(self):
self.item = Item('test')
self.wrapper = Wrapper(self.item)
self.empty_wrapper = EmptyWrapper()
def test_proxy_method_call(self):
string = self.wrapper.test('message')
self.assertEqual(string, 'message was passed on')
def test_normal_attribute_not_proxied(self,):
with self.assertRaises(AttributeError):
self.wrapper.name
self.wrapper.name()
def test_empty_wrapper_raises_error(self,):
with self.assertRaises(NotImplementedError):
self.empty_wrapper.test('message')
if __name__ == '__main__':
unittest.main()
- 1. Objective C/iOSのruby method_missingに相当する
- 2. Rubyに相当するPython "_"
- 3. Ruby Array.eachメソッドに相当するPython
- 4. PythonでRuby on Railsに相当する
- 5. Pythonに相当するRuby `if __FILE__ == $ PROGRAM_NAME`
- 6. Ruby - method_missing
- 7. ruby file_get_contents相当の
- 8. Pygame相当のRuby?
- 9. Pythonのdefaultdictに相当するRubyは何ですか?
- 10. Pythonのリストの理解に相当するRuby
- 11. rubyの文字列inspect()に相当するのはPythonで
- 12. ruby rspecの "skip"と "pending"に相当するPython
- 13. Rubyのサンドイッチブロックコードに相当するC#式。
- 14. Rubyのa ||に相当するJQuery b
- 15. PHPの$に相当するRuby
- 16. RubyのString#scanに相当するJavaScript
- 17. Rubyの "pass"に相当する
- 18. Zend_Form ruby/railsに相当する
- 19. groovy(ruby)に相当するsortby?
- 20. C++ enumに相当するRuby/Rails
- 21. Rubyシンボルに相当するObjective-C
- 22. metric_fu ruby 1.9.xに相当する
- 23. Rubyに相当するC++ Const?
- 24. 〜/ .bashrcに相当するPython
- 25. find2perlに相当するPython
- 26. Pythonに相当するPropertyUtilsBean
- 27. 'pat2cwav'に相当するPython
- 28. Jstackに相当するPython?
- 29. Rubyのirb相当のPerl?
- 30. Rubyは "相当"です
ありがとうございます。私はちょっとグーグルで[this](http://venodesigns.net/2010/11/02/emulating-rubys-method_missing-in-python/)を見つけました。 – missingfaktor
参考までに、問題となるリンクは、メソッドとみなすべき属性名のリストを定義することであいまいさを取り除きます(これらのメソッドのそれぞれを_define_してスタブに委譲できるので、目的を少し破るように思えます)。 –