您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

绑定和未绑定方法对象的id()-有时对于不同的对象相同,有时对于相同的对象不同

绑定和未绑定方法对象的id()-有时对于不同的对象相同,有时对于相同的对象不同

每当您通过instance.name(和在Python 2中class.name)通过查找方法时,都会重新创建该方法对象。Python每次都使用描述符协议函数包装在方法对象中。

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

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

请参阅有关文档id()

返回对象的“身份”。这是一个整数(或长整数),在此对象的生存期内,此整数保证是唯一且恒定的。 。

:这是对象在内存中的地址。

强调我的。

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

>>> 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_METHOD-CALL_METHOD操作码对,以精确地替换当前的LOAD_ATTRIBUTE-CALL_FUNCTION操作码对,以避免每次都创建一个新的方法对象。这种优化变换executon路径instance.foo()type(instance).__dict__['foo'].__get__(instance, type(instance))()type(instance).__dict__['foo'](instance)“手动”,所以在该实例通过直接向功能对象。

其他 2022/1/1 18:45:07 有435人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶