我最近遇到了this recipe因为做了一个“弱方法”,并认为这是蜜蜂的膝盖;但似乎有一个神秘的论点被传递给我似乎无法找到的MethodType
函数:
from weakref import proxy
from types import MethodType
class Foo(object):
def __getattribute__(self, name):
if name.startswith('foo_'):
return MethodType(super(Foo, self).__getattribute__(name), proxy(self), self.__class__)
else:
return super(Foo, self).__getattribute__(name)
class Bar(Foo):
def my_func(self, a, b):
print a, b
def foo_my_func(self, a, b):
print 'FF Victory Theme'
>>> bar = Bar()
>>> bar.my_func(1, 2)
1 2
>>> weakmethod = bar.foo_my_func
>>> weakmethod(2, 3) # Or `bar.foo_my_func(2, 3)`
Traceback (most recent call last):
File "<pyshell#160>", line 1, in <module>
weakmethod(2, 3)
TypeError: foo_my_func() takes exactly 3 arguments (4 given)
第四个被传递的论点是什么?
答案 0 :(得分:1)
您使用super(Foo, self).__getattribute__(name)
来访问foo_my_func
方法。此已返回MethodType
个对象。然后再次 。
因此,您返回的对象将proxy(self)
传递给包装方法,该方法传递另一个 self
参数。您从a, b
开始,最后得到self, proxy(self), a, b
。
您链接的食谱使用装饰器;这个装饰器在类定义时执行,并包装函数对象。它本身就是一个描述符,因此它直接处理所有包装。
您希望解开 super(Foo, self).__getattribute__(name)
的结果,或者根本不使用__getattribute__
。
通过访问方法的__func__
属性可以完成展开:
class Foo(object):
def __getattribute__(self, name):
attr = super(Foo, self).__getattribute__(name)
if name.startswith('foo_'):
return MethodType(attr.__func__, proxy(self), self.__class__)
return attr
不使用__getattribute__
是通过直接访问该类的__dict__
映射来完成的:
class Foo(object):
def __getattribute__(self, name):
if name.startswith('foo_'):
for cls in type(self).__mro__:
if name in cls.__dict__:
return MethodType(cls.__dict__[name], proxy(self), self.__class__)
return super(Foo, self).__getattribute__(name)
其中type(self).__mro__
允许您以方法解析顺序迭代类及其基类,以手动搜索方法。