问题描述
我正在寻找有关如何存储在对象内部的对象上调用的方法的pythonic解决方案.
I'm looking for a pythonic solution on how to store a method which is called on an object right inside the object.
因为在python中,如果我想捕获例如abs()
方法,我将像这样重载该运算符:
Because in python, if I want to catch for example the abs()
method, I will overload this operator like:
Catcher(object):
def __abs__(self):
self.function = abs
c = Catcher()
abs(c) # Now c.function stores 'abs' as it was called on c
如果我想捕获一个具有其他属性的函数,例如pow()
,我将使用此函数:
If I want to catch a function, which have an other attribute in it, for example pow()
, I'm going to use this:
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'
现在,我正在寻找的是一种通用解决方案,可以捕获和存储在Catcher
上调用的任何类型的函数,而无需实现所有重载和其他情况.如您所见,我还想存储方法的属性值(如果有多个,则在列表中.?).
Now, what I'm looking for is a general solution, to catch and store any kind of function called on Catcher
, without implementing all overloads, and other cases. And as You can see, I also want to store the values (maybe in a list, if there is more than one of them?) which are the attributes of a method.
提前谢谢!
推荐答案
元类在这里无济于事;尽管将在当前对象的类型上查找特殊方法(因此,实例的类),但在执行此操作时未参考__getattribute__
或__getattr__
(可能是因为它们本身是特殊方法).因此,要捕获 all 所有dunder方法,就必须全部创建它们.
A metaclass won't help here; although special methods are looked up on the type of the current object (so the class for instances), __getattribute__
or __getattr__
are not consulted when doing so (probably because they are themselves special methods). So to catch all dunder methods, you are forced to create them all.
您可以通过枚举operator 特殊方法列表(__pow__
,__gt__
等). org/2/library/operator.html"rel =" noreferrer> operator
模块:
You can get a pretty decent list of all operator special methods (__pow__
, __gt__
, etc.) by enumerating the operator
module:
import operator
operator_hooks = [name for name in dir(operator) if name.startswith('__') and name.endswith('__')]
通过该列表可以添加类装饰器:
Armed with that list a class decorator could be:
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
然后将其应用于您的班级:
Then apply that to your class:
@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__
,我们仍然会迷上它.
So, even though our class doesn't define __pow__
explicitly, we still hooked into it.
这篇关于如何捕获在python中的对象上调用的任何方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!