Python中使用MethodType的优势

34

使用 types 模块中的 MethodType 有什么优点?您可以使用它向对象添加方法。但是,我们可以不使用它轻松地完成这个功能:

def func():
   print 1

class A:
   pass

obj = A()
obj.func = func
即使我们通过运行 del func 删除主作用域中的 func,它也可以工作。
为什么有人想使用 MethodType?这只是一种约定还是良好的编程习惯?

3
然而这并没有给 obj 添加一个方法。obj.func() 与仅调用 func() 相同。方法会将实例作为第1个位置参数接收。您可以使用 func.__get__(obj, A) 创建绑定方法,但这也行不通,因为 func 不接受任何参数。 - Ilja Everilä
3
您的函数func没有self参数。当您想要附加或替换类的方法时,请使用type。在这里,您只是将一个函数附加到类上。 - Cyrbil
2个回答

61

实际上,在运行时动态添加方法和您的示例之间存在巨大的区别:

  • 在您的示例中,您只是将函数附加到对象上,当然可以调用它,但它是未绑定的,它与对象本身没有关系(即您不能在函数内部使用self
  • 当使用MethodType添加时,您创建了一个绑定的方法,它会像普通的Python方法一样为对象行为,您必须将其所属的对象作为第一个参数(通常称为self),并且您可以在函数内部访问它。

这个例子展示了这个区别:

def func(obj):
  print 'I am called from', obj
class A:
  pass
a=A()
a.func=func
a.func()

这会导致一个 TypeError 错误: func()接受1个参数,但没有给出0个参数,而下面的代码则按预期工作:

import types
a.func = types.MethodType(func, a) # or types.MethodType(func, a, A) for PY2
a.func()

显示我被称为来自<__main__.A实例在xxx>


简而言之,这意味着我将无法使用我在其上使用的对象的属性。例如,如果在我的定义中有一个名为att的属性,那么我将无法使用它,对吗? - Existent
在你的问题中,函数与对象是解耦的。因为该函数根本不是一个方法,所以无法从函数中访问对象。 - mguijarr
@ABHI 不,att 可以从任何地方访问,但是你需要一个类的实例来访问它(即 att 本身没有意义,你需要 obj.att)。通常定义的方法(因此是绑定的)会得到 self 参数,它是该方法绑定到的实例,因此它们有一种简单的方法来获取适当的 att - Alex Hall
7
请注意,在Python 3中,types.MethodType只接受两个参数,因此对于此示例,调用方式为types.MethodType(func, a) - jpyams

7
types.MethodType 的常见用途是检查某个对象是否为方法。例如:
>>> import types
>>> class A(object):
...     def method(self):
...         pass
...
>>> isinstance(A().method, types.MethodType)
True
>>> def nonmethod():
...     pass
...
>>> isinstance(nonmethod, types.MethodType)
False

请注意,在您的示例中,isinstance(obj.func, types.MethodType)返回False。假设您在类A中定义了一个方法meth,那么isinstance(obj.meth, types.MethodType)将返回True

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接