Python中调用方法的不同方式,它们是如何工作的?

Python中调用方法的不同方式,它们是如何工作的?,python,class,object,Python,Class,Object,上面的代码给出了以下结果: class Test(): def a(self): return 6 Test_instance=Test() print(Test.a(Test_instance)) print(Test_instance.a()) print(Test.a(Test_instance,3)) print(Test_instance.a(3)) 如果排除printTest.aTest_实例3行,则得到相同的打印输出。但是,一个测试类和测试实例对象不都是一

上面的代码给出了以下结果:

class Test():
    def a(self):
        return 6
Test_instance=Test()
print(Test.a(Test_instance))
print(Test_instance.a())
print(Test.a(Test_instance,3))
print(Test_instance.a(3))
如果排除printTest.aTest_实例3行,则得到相同的打印输出。但是,一个测试类和测试实例对象不都是一个方法吗?当我写Test\u instance.a时,我给Test\u实例的a方法一个参数,当我写Test.a时,我给Test\u实例的a方法两个参数。但是错误是Test.aTest_实例3给出了两个参数。不应该是3吗?

执行instance.a时,instance作为第一个参数隐式传递。在执行instance.a3时,您会给出两个参数:隐式第一个实例和显式第三个,这是您的函数无法处理的

当您执行Test.a时,Test不会作为隐式第一个参数传递,因为a未定义为类方法。 如果你这样做

6
6
TypeError: a() takes 1 positional argument but 2 were given
然后尝试Test.a123会给您一个错误,即取1个位置参数,但取2个位置参数

或者Test.aTest_instance,3,您将得到预期的错误。

执行instance.a时,instance作为第一个参数隐式传递。在执行instance.a3时,您会给出两个参数:隐式第一个实例和显式第三个,这是您的函数无法处理的

当您执行Test.a时,Test不会作为隐式第一个参数传递,因为a未定义为类方法。 如果你这样做

6
6
TypeError: a() takes 1 positional argument but 2 were given
然后尝试Test.a123会给您一个错误,即取1个位置参数,但取2个位置参数

例如,3,您将得到预期的错误

但是,测试对象和测试实例对象不都是一种方法吗

的确如此

当我写Test\u实例时,我提供给一个Test\u实例的方法一个参数,当我写Test.aTest\u实例时,我提供给一个Test方法两个参数

对。但这只适用于实例上的方法调用

但是错误是Test.aTest_实例3给出了两个参数。不应该是3岁吗

不,它是2,因为您直接在类上而不是通过实例调用该方法

直接在类上调用方法会按原样调用它

但是,在实例上调用方法会将实例作为第一个参数进行前置

原因在于内部结构

如果我执行instance.X,那么X是类成员并实现了_get__方法描述符协议,在内部调用X._uget__,并为instance.X生成结果

函数实现描述符协议,以创建实例方法对象,该对象负责将实例作为第一个参数进行前置

因此,在您的示例中,您也可以这样做

class Test():
    @classmethod
    def a(self):
        return 6
这两个绑定方法都是我所说的实例方法对象

这方面的其他例子:

>>> print(Test_instance.a)
<bound method Test.a of <__main__.Test instance at 0x7f6e232e3690>>
>>> Test.a.__get__(Test_instance, Test)
<bound method Test.a of <__main__.Test instance at 0x7f6e232e3690>>
这里发生了什么

Test.x获取Test的x成员并调用其.\uuuu get\uuuuuux,None,Test。此方法返回设置为Test的b,因为a参数为None

inst.x获取Test的x成员并调用其.\uuu get\uuuuu x,inst,Test。这反过来又返回a

以类似的方式,方法被设置为工作

属性也使用相同的机制,顺便说一句

如果使用@classmethod和@staticmethod装饰器,它们会将函数包装到一些包装对象中,这些包装对象的行为稍有不同

但是,测试对象和测试实例对象不都是一种方法吗

的确如此

当我写Test\u实例时,我提供给一个Test\u实例的方法一个参数,当我写Test.aTest\u实例时,我提供给一个Test方法两个参数

对。但这只适用于实例上的方法调用

但是错误是Test.aTest_实例3给出了两个参数。不应该是3岁吗

不,它是2,因为您直接在类上而不是通过实例调用该方法

直接在类上调用方法会按原样调用它

但是,在实例上调用方法会将实例作为第一个参数进行前置

原因在于内部结构

如果我执行instance.X,那么X是类成员并实现了_get__方法描述符协议,在内部调用X._uget__,并为instance.X生成结果

函数实现描述符协议,以创建实例方法对象,该对象负责将实例作为第一个参数进行前置

因此,在您的示例中,您也可以这样做

class Test():
    @classmethod
    def a(self):
        return 6
这两个绑定方法都是我所说的实例方法对象

这方面的其他例子:

>>> print(Test_instance.a)
<bound method Test.a of <__main__.Test instance at 0x7f6e232e3690>>
>>> Test.a.__get__(Test_instance, Test)
<bound method Test.a of <__main__.Test instance at 0x7f6e232e3690>>
这里发生了什么

Test.x获取Test的x成员并调用其.\uuuu get\uuuuuux,None,Test。此方法返回设置为Test的b,因为a参数为None

inst.x获取Test的x成员并调用其.\uuu get\uuuuu x,inst,Test。这反过来又返回a

以类似的方式,方法被设置为工作

属性也使用相同的机制,顺便说一句

如果你
使用@classmethod和@staticmethod decorators,它们将函数包装到一些包装对象中,这些包装对象的行为稍有不同。\uuu获取\uuu行为。

不要描述类,而是将代码作为块发布!你有太多的文字描述你的代码,却没有给出一个简单的例子。您在解释代码时的冗长可以完全用实际代码代替,这将更好地帮助我们理解您的问题。对不起,我编辑了您的代码,而不是描述您的类,将您的代码作为块发布!你有太多的文字描述你的代码,却没有给出一个简单的例子。您在解释代码时的冗长可以完全替换为实际代码,这将更好地帮助我们理解您的问题。对不起,我编辑了当我们在测试中定义实例方法时,我们为测试实例和测试对象本身创建了一个方法,对吗?部分正确。您可以通过Test.a123之类的类访问实例函数,但是您故意以非预期的方式使用它。用@classmethod或@sstaticmethod修饰函数会告诉python您希望第一个参数如何工作。更多信息,当我们在测试中定义实例方法时,我们为测试实例和测试对象本身创建了一个方法,对吗?部分正确。您可以通过Test.a123之类的类访问实例函数,但是您故意以非预期的方式使用它。用@classmethod或@sstaticmethod修饰函数会告诉python您希望第一个参数如何工作。更多信息和