简体   繁体   English

python 中的方法与类相关联。 与实例直接关联的函数意味着什么?

[英]Methods in python are associated with the class. what does a function associated directly with the instance imply?

I know that in python, methods are associated the class and not the instance but they accept the instance as their first argument so as to access it.我知道在 python 中,方法与类而不是实例相关联,但它们接受实例作为他们的第一个参数以便访问它。 but, one can still define a function and tie it to an instance directly.但是,仍然可以定义一个函数并将其直接绑定到一个实例。 What does this imply?这意味着什么? and can this function somehow access the instance?这个函数可以以某种方式访问​​实例吗?

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 also allows this: 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

The two snippets above mean the same thing.上面两个片段的意思是一样的。 but python also allows this:但是 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

difference between the second and the third snippet is that the method defined outside is tied to the instance in latter, and to the class in the former.第二个和第三个片段之间的区别在于,外部定义的方法与后者的实例相关,而前者与类相关。

When you access a method through an instance, but the method lives on the class, accessing the method actually creates a method wrapper.当您通过实例访问方法,但该方法存在于类中时,访问该方法实际上会创建一个方法包装器。 This wrapper knows what instance the method was called on, and passes it through to the actual function as the first argument (named, by convention, self ).这个包装器知道调用该方法的实例,并将它作为第一个参数传递给实际函数(按照约定命名为self )。 The mechanism behind this is the descriptor protocol and it's how properties work, too.这背后的机制是描述符协议,它也是属性的工作方式。

When you put the method directly on the instance, none of that applies and it's just a function that you access by way of the instance.当您将方法直接放在实例上时,这些都不适用,它只是您通过实例访问的一个函数。 It doesn't get self .它不会得到self

Now, you can create a method wrapper by manually invoking the descriptor, and set the resulting bound method on the instance.现在,您可以通过手动调用描述符来创建方法包装器,并在实例上设置生成的绑定方法。

my_obj.method1 = method1_defined_outside.__get__(my_obj)

Now my_obj.method1() passes my_obj as self .现在my_obj.method1()my_obj作为self传递。

The situations in which you'd want to set a method on an instance like this are fairly rare, though.但是,您希望在这样的实例上设置方法的情况相当罕见。

One way you could force sending the instance as self is by using the functools.partial wrapper as:您可以强制将实例作为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()

which will yield in the console:这将在控制台中产生:

EXTERNAL 10

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM