传递给我的`MethodType`的隐藏参数是什么?

时间:2014-05-24 18:26:11

标签: python

我最近遇到了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)

第四个被传递的论点是什么?

1 个答案:

答案 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__允许您以方法解析顺序迭代类及其基类,以手动搜索方法。