[英]Using function as an instance method with Enthought Traits (Python)
我想创建一个基于函数的实例方法,作为实例初始化的参数,如下所示:
from traits.api import *
class C(HasTraits):
f = Function
c = C(f=lambda self: self)
但是,如果我跑步
c.f()
它说(毫不奇怪)
TypeError: <lambda>() takes exactly 1 argument (0 given)
将f从Function更改为Method并没有帮助,因为它不接受function参数(需要instancemethod)。
所以我的问题是,如何在使用Traits时让自定义函数充当实例方法(将self参数用作普通实例方法)?
一个函数(无论是用lambda
还是def
定义的)都不是方法。
您不能只更改其类型; 方法比函数具有更多的信息-它与对象绑定。 这就是Python知道第一个( self
)参数传递什么的方式。
在您的情况下,您正在寻找未绑定方法 ,该方法未绑定到对象,但仍绑定到类 。
在正常情况下(当你def
一个内部的方法class
的定义,然后创建类的实例,然后调用一个方法就可以了),这为您自动发生。 (有关更多详细信息,请参见方法的工作原理 。)但是,当您自己完成所有操作时,您需要自己创建绑定方法。
与Python中的其他任何类型一样,您可以通过将该类型称为构造函数来实现。 问题是“绑定方法”不能作为内置类型访问。 这意味着您必须转到types
模块,该模块“为标准Python解释器使用的某些对象类型定义名称”。 像这样:
bound = types.MethodType(func, my_obj, type(my_obj))
unbound = types.UnboundMethodType(func, None, my_type)
但是请注意,通常没有充分的理由执行此操作-您可以轻松地将对象塞入闭包中。 这些可调用对象都将执行相同的操作:
func = lambda self: self
bound = types.MethodType(func, my_obj, type(my_obj))
func2 = lambda: my_obj
func3 = lambda self: self
unbound = types.UnboundMethodType(func, None, my_type)
func3a = lambda: unbound(my_obj)
最后两个想法:
如果您了解描述符 ,那么使@property
起作用的魔力和使绑定方法起作用的魔力将相互干扰。 我不知道Enthough特质是否正确,但事实可能如此。 因此,您的问题的答案很可能是“您无法做到”。 取而代之的是,您将必须先创建一个Function
特征,然后创建一个包装器方法,以显式调用该特征。
如果使用Python 3.x而不是2.x,则未绑定的方法会消失(类仅使用简单的旧函数),因此您遇到的许多复杂性都不会出现。
如下定义新的Trait类型MyMethod:
import types
class MyMethod(TraitType):
def validate(self, object, name, value):
if isinstance(value, types.MethodType):
return value
if isinstance(value, types.FunctionType):
return types.MethodType(value, object, object.__class__)
self.error(object, name, value)
并使用它代替之前的代码中的Function或Method,函数将自动转换为实例方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.