我试图在新样式的类中拦截对python的双下划线魔术方法的调用。这是一个微不足道的例子,但它表明了目的:
class ShowMeList(object):
def __init__(self, it):
self._data = list(it)
def __getattr__(self, name):
attr = object.__getattribute__(self._data, name)
if callable(attr):
def wrapper(*a, **kw):
print "before the call"
result = attr(*a, **kw)
print "after the call"
return result
return wrapper
return attr
如果我在list周围使用代理对象,我会得到非magic方法的预期行为,但是我的包装函数从来没有为magic方法调用过。
>>> l = ShowMeList(range(8))
>>> l #call to __repr__
<__main__.ShowMeList object at 0x9640eac>
>>> l.append(9)
before the call
after the call
>> len(l._data)
9
如果我没有从对象继承(第一行class ShowMeList:
),那么一切都按预期工作:
>>> l = ShowMeList(range(8))
>>> l #call to __repr__
before the call
after the call
[0, 1, 2, 3, 4, 5, 6, 7]
>>> l.append(9)
before the call
after the call
>> len(l._data)
9
如何使用新样式类完成此截取?
使用
__getattr__
和__getattribute__
是类的最后一个响应获取属性的资源。请考虑以下几点:
__getattr__
方法只在其他方法不起作用时调用(它对运算符不起作用,您可以阅读有关该方法的here)。在您的示例中,
__repr__
和许多其他magic方法已经在object
类中定义。有一件事可以做,思想,它是定义那些神奇的方法,然后使然后调用
__getattr__
方法。请检查我提出的另一个问题及其答案(link)以查看某些代码正在执行此操作。出于性能原因,Python总是在类(和父类)中查找magic方法,而不使用常规的属性查找机制。解决方法是在创建类时使用元类自动为magic方法添加代理;例如,我使用此技术避免了通过包装类的方法编写样板调用。
用法:
对于Asymmetric behavior for __getattr__, newstyle vs oldstyle classes(另请参见Python docs)的答案,使用
__getattr__
或__getattribute__
修改对“magic”方法的访问权限对于新样式的类是不可能的。这个限制使解释器更快。相关问题 更多 >
编程相关推荐