我知道可以定义一个函数并将其用作方法:
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
?
答案 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
注意:
__get__
并生成合法的绑定方法对象,但是这样您就可以拥有self
和 {{1} }。obj
为obj
(None
,而不是Test.method1
);您可以分别决定在这种情况下的处理方式(使用Test().method1
。