python - Python中调用方法的不同方式,它们是如何工作的?
问题描述
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))
上面的代码给了我以下结果:
6
6
TypeError: a() takes 1 positional argument but 2 were given
如果我排除该行print(Test.a(Test_instance,3))
,我会得到相同的打印输出。但是,不是类和对象a
的方法吗?当我写作时,我假设我给 of 的方法一个参数,而当我写作时,我假设我给of 的方法两个参数。但是错误说这给出了 2 个参数。不应该是3吗?Test
Test_instance
Test_instance.a()
a()
Test_instance
Test.a(Test_instance)
a()
Test
Test.a(Test_instance,3)
解决方案
但是“a”不是Test对象和Test_instance对象的方法吗?
这的确是。
当我写作时,我假设我给Test_instance的“a”方法
Test_instance.a()
一个参数,而当我写作时,我假设我给Test的“a”方法两个参数。Test.a(Test_instance)
正确的。但这仅适用于实例上的方法调用。
但是错误说这
Test.a(Test_instance,3)
给出了 2 个参数。不应该是3吗?
不,它是 2,因为您直接在类上调用该方法,而不是通过实例。
直接在类上调用方法会按原样调用它。
但是,在实例上调用方法会将实例作为第一个参数添加。
造成这种情况的原因是内部因素。
如果我这样做instance.X
,X
是一个类成员并实现__get__()
方法(描述符协议),在内部X.__get__()
被调用并为instance.X
.
并且函数实现描述符协议以创建实例方法对象,该对象负责将实例作为第一个参数。
所以,在你的例子中,你也可以这样做
>>> 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>>
这两种“绑定方法”都是我所说的“实例方法对象”。
其他示例:
class Desc(object):
def __get__(self, a, b):
print('Calling __get__(%r, %r, %r)' % (self, a, b))
return a or b
class Test():
x = Desc()
>>> Test.x
Calling __get__(<__main__.Desc object at 0x7f6e232e1810>, None, <class __main__.Test at 0x7f6e232ea050>)
<class __main__.Test at 0x7f6e232ea050>
>>> inst = Test()
>>> inst.x
Calling __get__(<__main__.Desc object at 0x7f6e232e1810>, <__main__.Test instance at 0x7f6e232e3c80>, <class __main__.Test at 0x7f6e232ea050>)
<__main__.Test instance at 0x7f6e232e3c80>
这里会发生什么?
Test.x
接受x
成员Test
并调用其.__get__(x, None, Test)
. 此方法返回b
(设置为Test
),因为a
参数是None
。
inst.x
接受x
成员Test
并调用其.__get__(x, inst, Test)
. 这反过来又回来了a
。
以类似的方式,方法被设置为工作。
属性也使用相同的机制,顺便说一句。
如果您使用@classmethod
and装饰器,它们会将函数包装到一些行为@staticmethod
略有不同的包装对象中。.__get__()
推荐阅读
- excel - 如何将宏应用于整个列?
- r - 在RMarkdown中以错误的顺序输出R中的for循环
- php - 有没有办法直接重定向下载流请求,而不是下载文件两次(由服务器然后由用户)?
- spring-boot - 将新条目添加到 postgree 数据库时如何将数据发送到 ionic 4?
- java - 如何设计批量 GET 调用?
- apollo - 如何在 next.js 中改变 apollo 上下文?
- c++ - 本征为零,但在每个矩阵元素上
- python - 在熊猫数据框中解压缩具有与索引相似值的行?
- sql-server - SSIS - 从不同的数据库中查找记录
- javascript - 如何并排排序 html javascripts 明信片?