ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python – 绑定和未绑定方法对象的id() – 有时对于不同对象是相同的,有时对于同一对象是不同的

2019-09-15 12:56:18  阅读:122  来源: 互联网

标签:python object methods


我已经尝试了一些关于绑定和未绑定方法的代码.当我们调用它们时,我认为它们都会返回对象.但是当我使用id()获取一些信息时,它会返回一些我不理解的东西.

IDE:Eclipse

插件:pydev

Class C(object):
    def foo(self):
        pass

cobj = C()

print id(C.foo)    #1
print id(cobj.foo) #2

a = C.foo
b = cobj.foo

print id(a)        #3
print id(b)        #4

输出是……

5671672

5671672

5671672

5669368

为什么#1和#2返回相同的ID?它们不是不同的对象吗?如果我们将C.foo和conj.foo分配给两个变量,#3和#4将返回不同的id.

我认为#3和#4表明它们不是同一个对象,但#1和#2 ……

绑定方法的id和未绑定方法有什么区别?

解决方法:

无论何时通过instance.name(以及Python 2,class.name)查找方法,都会创建一个方法对象a-new. Python每次使用descriptor protocol将函数包装在方法对象中.

因此,当您查找id(C.foo)时,会创建一个新的方法对象,您将检索其id(内存地址),然后再次丢弃该方法对象.然后你查找id(cobj.foo),一个新的方法对象,它重新使用现在释放的内存地址,你会看到相同的值.然后,再次丢弃该方法(随着引用计数降至0,垃圾收集).

接下来,您在变量中存储了对C.foo未绑定方法的引用.现在不释放内存地址(引用计数为1,而不是0),并通过查找必须使用新内存位置的cobj.foo来创建第二个方法实例.因此,您获得两个不同的值.

documentation for id()

Return the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

CPython implementation detail: This is the address of the object in memory.

强调我的.

您可以通过类的__dict__属性直接引用函数来重新创建方法,然后调用__get__ descriptor method

>>> class C(object):
...     def foo(self):
...         pass
... 
>>> C.foo
<unbound method C.foo>
>>> C.__dict__['foo']
<function foo at 0x1088cc488>
>>> C.__dict__['foo'].__get__(None, C)
<unbound method C.foo>
>>> C.__dict__['foo'].__get__(C(), C)
<bound method C.foo of <__main__.C object at 0x1088d6f90>>

请注意,在Python 3中,已经删除了整个未绑定/绑定方法的区别;你得到一个函数,在你得到一个未绑定的方法之前,和一个方法,否则,方法总是绑定:

>>> C.foo
<function C.foo at 0x10bc48dd0>
>>> C.foo.__get__(None, C)
<function C.foo at 0x10bc48dd0>
>>> C.foo.__get__(C(), C)
<bound method C.foo of <__main__.C object at 0x10bc65150>>

此外,Python 3.7添加了一个新的LOAD_METHODCALL_METHOD操作码对,它可以精确地替换当前的LOAD_ATTRIBUTE – CALL_FUNCTION操作码对,以避免每次都创建一个新的方法对象.此优化从类型(实例)转换instance.foo()的执行路径.__ dict __ [‘foo’] .__ get __(instance,type(instance))()with type(instance).__ dict __ [‘foo’](instance ),所以’手动’将实例直接传递给函数对象.

标签:python,object,methods
来源: https://codeday.me/bug/20190915/1804876.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有