Python的等價於Ruby的method_missing
方法是什麼?我試過使用__getattr__
,但這個鉤子也適用於字段。我只想攔截方法調用。 Python的方式是什麼?Python的等價Ruby的'method_missing'
回答
Python與屬性和方法沒有區別。方法只是一個屬性,其類型只是instancemethod
,恰好可以調用(支持__call__
)。
如果要實現這一點,您__getattr__
方法應該返回一個函數(lambda
或正def
,無論您需求),也許檢查調用之後的東西。
Python沒有像Ruby那樣區分方法和屬性(又名「實例變量」)。在Python中查找方法和其他對象屬性的方式完全相同 - 甚至Python在查找階段都不知道其差異。直到找到屬性,它只是一個字符串。
所以,如果你問的方式,以確保__getattr__
是只呼籲方法,我怕你可能不會找到一個完美的解決方案。但是簡單地從__getattr__
返回一個函數(甚至是全新的dynamically bound method)是很容易的。
出於同樣的原因您可以在Ruby中使用'method_missing'或在Smalltalk中使用'doesNotUnderstand'。 – missingfaktor
我明白你爲什麼要使用'__getattr__'。我只是不明白你爲什麼「只想攔截方法調用」。 – senderle
我的設計並不需要攔截字段訪問,但它似乎不是一個很大的絆腳石。我發現@Emil提供的解決方案足夠滿足我的要求。 – missingfaktor
雖然我不推薦它!!!!!!!!!!!!!!!!!!!!!
這種接近於實現調用特殊方法的行爲,爲每個不符合可調用屬性/方法的名稱調用特殊方法。當然,它們還沒有真正的單獨命名空間,所以它可能會感覺有點奇怪。它的工作原理是覆蓋__getattribute__
,它在較低級別上工作,然後__getattr__
它嘗試在屬性失敗時取回屬性,它返回一個curried特殊方法,用您調用的名稱進行調用,如果它成功則將其傳遞,否則它將被調用 用代理對象包裝結果,該代理對象之後的行爲幾乎完全相同,除了它使用特殊方法實現調用。
它不允許你訪問調用對象,因爲如果它已經是一個你可以存儲的非可調用屬性,我想不出一種不會泄漏內存(調用對象)的好方法。我能想到的唯一想法是啓動一個新的線程,在一分鐘後刪除它,那麼你可能已經調用了它,除非你在封閉中使用它,在這種情況下不會被支持)。
編輯:我忘了callable可能有一些誤報。
依賴於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. Ruby的等價的Python setattr()
- 2. 與其他語言中的Ruby的method_missing是否等價?
- 3. python等價於ruby的__method__?
- 4. python等價於ruby的StringScanner?
- 5. Ruby等價於Python的DictWriter?
- 6. python等價於ruby的`map.with_index`?
- 7. python等價於ruby bundler包
- 8. Python的for Ruby的等價物
- 9. Python的等價物Ruby的each_slice(count)
- 10. Python的延續與Ruby的等價物
- 11. Ruby的等價的Python str [3:]
- 12. Ruby是否有未定義的實例變量的method_missing等價物?
- 13. Python等價於Ruby的包函數
- 14. 是否有「python -i」的ruby等價物?
- 15. Ruby的watchr在Python中等價嗎?
- 16. Python中的「require」(Ruby)等價於什麼?
- 17. Python`itertools.chain`的Ruby等價物是什麼?
- 18. 的Ruby的method_missing參數
- 19. Ruby的等價ASP.NET的Application_Start?
- 20. Ruby的cURL的等價物?
- 21. 如何調試Ruby的method_missing?
- 22. ruby中定義的method_missing
- 23. C#等價的Ruby符號
- 24. Ruby的等價PHP openssl_seal
- 25. Java的Ruby等價物ObjectSpace.each_object
- 26. Ruby中subprocess.Popen()的等價物?
- 27. Ruby的等價LINQ ToList()
- 28. R中的method_missing等效於
- 29. Python的等價物@
- 30. Python的等價性?
謝謝。我在Google上找到了[this](http://venodesigns.net/2010/11/02/emulating-rubys-method_missing-in-python/)。 – missingfaktor
作爲參考,有問題的鏈接通過定義應該被視爲方法的屬性名稱列表來避開歧義(這聽起來像是有點違背了目的,因爲您可以將這些方法中的每一個都定義並委託給存根)。 –