如何使用可调用对象作为方法定义?

时间:2019-01-04 19:30:58

标签: python python-2.7

我知道可以定义一个函数并将其用作方法:

def method(*args, **kwargs):
    print "%r %r" % (args, kwargs)

class Test(object):
    method1 = method

t = Test()
t.method1()  # (<__main__.Test object at 0x10705a4d0>,) {}

我想对可调用对象做同样的事情,像这样:

class Method(object):
    __call__ = method

class Test(object):
    method1 = Method()

但是,当我这样做时,self的{​​{1}}参数是方法本身(这是正常的),但是Method.__call__实例的self参数是迷路了。

Test

是否可以将t = Test() t.method1() # (<__main__.Method object at 0x10703f110>,) {} 参数作为第二个参数传递给self

2 个答案:

答案 0 :(得分:5)

通过将函数method封装在类中,可以有效地防止将对象绑定到函数从而创建方法的机制。这种工作方式是常规python函数是descriptors

总结文档:当您编写以下代码时:

some_instance.some_function()

使用some_function作为第一个参数调用__get__的{​​{1}}方法。然后,some_instance方法将返回一个绑定方法对象,该对象记住该实例。稍后,当绑定方法对象的__get__方法被调用时,它将保存的实例作为第一个参数传递。

我们可以重新实现这种行为:

__call__

在您的情况下,def method(*args, **kwargs): print("%r %r" % (args, kwargs)) class BoundMethod(object): # the bound method remembers the instance and the function def __init__(self, instance, function): self.instance = instance self.function = function # when the bound method is called, it passes the instance def __call__(self, *args, **kwargs): return self.function(self.instance, *args, **kwargs) class Method(object): # the __get__ method assembles a bound method consisting of the # instance it was called from and the function def __get__(self, instance, cls): return BoundMethod(instance, method) class Test(object): method1 = Method() t = Test() t.method1() # (<__main__.Test object at 0x7f94d8c3aad0>,) {} 不是描述符。因此,在内部请求Method属性(它是一个函数)时,它会绑定到包含类(__call__)的对象上。

我不确定这是否有用,因为该示例只是后台发生的事情的简化版本。

注意:在此示例中:

Method

第一张照片告诉我们,一个未绑定的方法从字面上称为class C: def function(self): pass print(C.function) print(C().function) ,而一个绑定的方法称为<unbound method C.function>

但是在python3中,第一张照片显示出未绑定方法只是我们在类中定义的未更改函数。

答案 1 :(得分:2)

是:将方法设置为描述符-正如Wombatz所指出的那样,这是常规方法绑定所使用的机制。

class Method(object):
  def __get__(self,obj,cls):
    def method(*args, **kwargs):
      print type(obj)   # to illustrate what object we get
      print type(self)  # we have the Method too
      print "%r %r" % (args, kwargs)
    return method

注意:

  1. 也可以转发到函数上的__get__并生成合法的绑定方法对象,但是这样您就可以拥有self {{1} }。
  2. 如果在类本身上查找方法,则
  3. objobjNone,而不是Test.method1);您可以分别决定在这种情况下的处理方式(使用Test().method1