Python 的 Rubymethod_missing
方法等价物是什么?我尝试使用__getattr__
,但这个钩子也适用于字段。我只想拦截方法调用。Python的方法是什么?
问问题
8265 次
3 回答
29
在 Python 中,属性和方法没有区别。方法只是一个属性,它的类型是 just instancemethod
,恰好是可调用的(支持__call__
)。
如果您想实现这一点,您的__getattr__
方法应该返回一个函数(alambda
或常规def
,无论您需要什么套件),并可能在调用后检查一些内容。
于 2011-07-15T08:22:26.540 回答
5
Python 不像 Ruby 那样区分方法和属性(也称为“实例变量”)。在 Python 中查找方法和其他对象属性的方式完全相同——甚至 Python 也不知道查找阶段的区别。在找到属性之前,它只是一个字符串。
因此,如果您要寻求一种方法来确保__getattr__
仅调用方法,恐怕您可能找不到优雅的解决方案。但是从. ___getattr__
于 2011-07-15T08:18:43.647 回答
3
您可以通过以下方式实现类似 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()
于 2013-08-31T19:36:31.933 回答