我知道在python中,方法是与类而不是实例相关联的,但是它们接受实例作为其第一个参数以便对其进行访问。但是,仍然可以定义一个函数并将其直接绑定到实例。这意味着什么?并且该函数可以以某种方式访问实例吗?
class TestClass:
def __init__(self, a):
self.a = a
def method1(self):
return self.a
my_obj = TestClass(12)
print(my_obj.method1()) // 12
Python也允许这样做:
class TestClass:
def __init__(self, a):
self.a = a
my_obj = TestClass(12)
def method1_defined_outside(self):
return self.a
TestClass.method1 = method1_defined_outside
print(my_obj.method1()) // 12
上面的两个片段含义相同。 但是python也允许这样做:
class TestCase:
def __init__(self, a):
self.a = a
my_obj = TestCase(12)
def method1_defined_outside(self):
return self.a
my_obj.method1 = method1_defined_outside
print(my_obj.method1()) // this throws an error stating the method1 is missing one postional argument(s), so clearly self does not automatically equate to the object
第二个片段和第三个片段之间的区别在于,外部定义的方法与后者中的实例以及前者中的类相关。
答案 0 :(得分:1)
当您通过实例访问方法但该方法存在于类中时,访问该方法实际上会创建一个方法包装器。该包装器知道调用该方法的实例,并将其作为第一个参数(按惯例命名为self
)传递给实际函数。其背后的机制是descriptor protocol,它也是属性的工作方式。
将方法直接放在实例上时,这些都不适用,它只是您通过实例访问的函数。它没有得到self
。
现在,您可以通过手动调用描述符创建方法包装器,并在实例上设置结果绑定方法。
my_obj.method1 = method1_defined_outside.__get__(my_obj)
现在my_obj.method1()
以my_obj
的身份通过self
。
在这种情况下,要在实例上设置方法的情况很少见。
答案 1 :(得分:0)
可以强制将实例发送为self
的一种方法是使用functools.partial
包装器,如下所示:
from functools import partial
class A:
def __init__(self):
self.x = 10
a1 = A()
def do_external(self):
print("EXTERNAL", self.x)
a1.doext = partial(do_external, a1)
a1.doext()
将在控制台中显示:
EXTERNAL 10