代码之家  ›  专栏  ›  技术社区  ›  zneak

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

  •  2
  • zneak  · 技术社区  · 6 年前

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

    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 论证 Method.__call__ 是方法本身(这是正常的),但是 自己 论证 Test 实例丢失。

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

    有没有可能 自己 作为第二个参数传递给 方法。 ?

    2 回复  |  直到 6 年前
        1
  •  5
  •   Wombatz    6 年前

    通过包装该函数 method 在类中,您有效地防止了将对象绑定到函数从而创建方法的机制。其工作方式是常规的python函数 descriptors .

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

    some_instance.some_function()
    

    这个 some_function S __get__ 方法是用调用的 some_instance 作为第一个参数。这个 第二代 然后,方法返回一个绑定方法对象,该对象会记住实例。稍后,当绑定方法对象的 __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 不是描述符。所以,当内部 阿尔卡拉尔 请求属性(函数),它绑定到包含类的对象( 方法 )

    我不确定这是否有用,因为这个例子只是引擎盖下发生的事情的简化版本。

    注:在本例中:

    class C:
        def function(self): pass
    
    print(C.function)
    print(C().function)
    

    第一张图告诉我们,一个未绑定的方法 <unbound method C.function> 当调用绑定方法时 <bound method C.function of ...> .

    然而,在python3中,第一次打印显示未绑定的方法只是我们在类中定义的未更改的函数。

        2
  •  2
  •   Davis Herring    6 年前

    是:使方法A 描述符 _“,正如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 obj 可用。
    2. OBJ None 如果方法在 类本身 ( Test.method1 而不是 Test().method1 );您可以单独决定要做什么(用 cls 在那种情况下。