我正在寻找有关如何存储在对象内部的对象上调用的方法的pythonic解决方案。
因为在python中,如果我想捕获例如abs()方法,我将像这样重载该运算符:
abs()
Catcher(object): def __abs__(self): self.function = abs c = Catcher() abs(c) # Now c.function stores 'abs' as it was called on c
例如,如果要捕获一个具有其他属性的函数,pow()我将使用此函数:
pow()
Catcher(object): def __pow__(self, value): self.function = pow self.value = value c = Catcher() c ** 2 # Now c.function stores 'pow', and c.value stores '2'
现在,我要寻找的是一种通用解决方案,可以捕获和存储on上调用的任何类型的函数Catcher,而无需实现所有重载和其他情况。如您所见,我还想存储方法的属性值(如果有多个,则 存储 在列表中? )。
Catcher
提前致谢!
元类在这里无济于事;尽管会根据当前对象的类型(例如实例的类)查找特殊方法,__getattribute__或者__getattr__在这样做时不对其进行查询(可能是因为它们本身就是特殊方法)。因此,要捕获 所有 dunder方法,您必须全部创建它们。
__getattribute__
__getattr__
你可以得到所有的一个相当不错的清单 运营商 的特殊方法(__pow__,__gt__等)通过枚举operator模块:
__pow__
__gt__
operator
import operator operator_hooks = [name for name in dir(operator) if name.startswith('__') and name.endswith('__')]
有了该列表,类装饰器可以是:
def instrument_operator_hooks(cls): def add_hook(name): operator_func = getattr(operator, name.strip('_'), None) existing = getattr(cls, name, None) def op_hook(self, *args, **kw): print "Hooking into {}".format(name) self._function = operator_func self._params = (args, kw) if existing is not None: return existing(self, *args, **kw) raise AttributeError(name) try: setattr(cls, name, op_hook) except (AttributeError, TypeError): pass # skip __name__ and __doc__ and the like for hook_name in operator_hooks: add_hook(hook_name) return cls
然后将其应用于您的班级:
@instrument_operator_hooks class CatchAll(object): pass
演示:
>>> c = CatchAll() >>> c ** 2 Hooking into __pow__ Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 11, in op_hook AttributeError: __pow__ >>> c._function <built-in function pow> >>> c._params ((2,), {})
因此,即使我们的类没有__pow__明确定义,我们仍然会迷上它。