如何使用types.MethodType?

7 python python-3.x

types.MethodType期望什么参数,返回什么? https://docs.python.org/3.6/library/types.html并未详细说明:

types.MethodType
Run Code Online (Sandbox Code Playgroud)

用户定义的类实例的方法类型。

例如,来自https://docs.python.org/3.6/howto/descriptor.html

为了支持方法调用,函数包括__get__()用于在属性访问期间绑定方法的方法。这意味着所有函数都是非数据描述符,它们根据是从对象还是从类调用而返回绑定或未绑定的方法。在纯python中,它的工作方式如下:

class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        if obj is None:
            return self
        return types.MethodType(self, obj)
Run Code Online (Sandbox Code Playgroud)
  • 必须在第一个参数selftypes.MethodType是一个可调用对象?换句话说,该类是否Function必须是可调用类型,即必须Function具有方法__call__

  • 如果 self 是可调用对象,它是否至少需要一个参数?

  • 是否types.MethodType(self, obj)意味着obj将第一个参数赋予可调用对象self,即self 与curring obj

  • 如何types.MethodType(self, obj) 创建并返回的实例types.MethodType

谢谢。

Blc*_*ght 5

通常你不需要创建types.MethodType自己的实例。相反,当您访问类实例上的方法时,您将自动获得一个。

例如,如果我们创建一个类,创建它的一个实例,然后访问该实例上的一个方法(不调用它),我们将得到一个types.MethodTypeback实例:

import types

class Foo:
    def bar(self):
        pass

foo = Foo()

method = foo.bar

print(type(method) == types.MethodType) # prints True
Run Code Online (Sandbox Code Playgroud)

您在问题中摘录的代码试图展示这通常是如何发生的。这不是您通常必须自己做的事情,但如果您真的愿意,您可以这样做。例如,要创建另一个types.MethodTypemethod上面等效的实例,我们可以这样做:

method_manual = types.MethodType(Foo.bar, foo)
Run Code Online (Sandbox Code Playgroud)

的第一个参数MethodType是一个可调用对象(通常是一个函数,但也可以是其他东西,Function例如您正在阅读的示例中的类的实例)。我们将函数绑定到的第二个参数。当您调用方法对象(使用 eg method())时,绑定对象将作为第一个参数传递到函数中。

通常方法绑定到的对象是一个实例,尽管它可以是其他东西。例如,一个classmethod装饰函数将绑定到它被调用的类,而不是一个实例。这是一个例子(自动获取绑定到类的方法,并自己手动完成):

class Foo2:
    @classmethod
    def baz(cls):
        pass

foo2 = Foo2()

method2 = Foo2.baz
method2_via_an_instance = foo2.baz
method2_manual = types.MethodType(method2.__func__, Foo2)
Run Code Online (Sandbox Code Playgroud)

所有三个method2-prefixed 变量的工作方式完全相同(当您调用它们时,它们都将调用bazwithFoo2作为cls参数)。这次手动方法唯一奇怪的地方是,如果baz不获取绑定方法,就很难获得原始函数,因此我从其他绑定方法对象之一中提取了它。

最后一点:名称types.MethodType是用于绑定方法的内部类型的别名,否则它没有可访问的名称。与许多类不同,repr实例的 不是重新创建它的表达式(它类似于"<bound method Foo.bar of <__main__.Foo object at 0x0000...>>")。repr类型的也不是访问类型的有效名称(repr"method")。


Dan*_*man -2

这不是你会调用的东西。与模块中的大多数类一样types,它更多地用于与现有对象进行比较(例如在 中isinstance)。