“a is b”和“a is b”有什么区别?和“id(a)==id(b)”在Python中?

发布于 2024-09-02 17:19:14 字数 998 浏览 3 评论 0原文

id() 内置函数给出...

一个整数(或长整数),保证该对象在其生命周期内是唯一且恒定的。

相反, is 运算符给出...

对象标识

那么,为什么两个对象可能具有相同的 id 但在 is 检查时返回 False 呢?这是一个例子:

>>> class Test():
...   def test():
...     pass
>>> a = Test()
>>> b = Test()
>>> id(a.test) == id(b.test)
True
>>> a.test is b.test
False

一个更令人不安的例子:(继续上面)

>>> b = a
>>> b is a
True
>>> b.test is a.test
False
>>> a.test is a.test
False

但是:

>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True

The id() inbuilt function gives...

an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime.

The is operator, instead, gives...

object identity

So why is it possible to have two objects that have the same id but return False to an is check? Here is an example:

>>> class Test():
...   def test():
...     pass
>>> a = Test()
>>> b = Test()
>>> id(a.test) == id(b.test)
True
>>> a.test is b.test
False

A more troubling example: (continuing the above)

>>> b = a
>>> b is a
True
>>> b.test is a.test
False
>>> a.test is a.test
False

However:

>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ら栖息 2024-09-09 17:19:14
>>> b.test is a.test
False
>>> a.test is a.test
False

每次查找方法时都会即时创建方法。函数对象(始终是同一个对象)实现描述符协议 及其 __get__ 创建绑定方法对象。通常没有两个绑定方法是同一个对象。

>>> id(a.test) == id(b.test)
True
>>> a.test is b.test
False

这个例子是骗人的。第一个结果为 True 纯属巧合。 a.test 创建一个绑定方法,并在计算 id(a.test) 后对其进行垃圾回收,因为没有任何对其的引用。 (请注意,您引用的文档说 id 是“该对象在其生命周期内是唯一且恒定的”(强调我的)。)b.test 发生 与之前的绑定方法具有相同的 id,这是允许的,因为现在没有其他对象具有相同的 id。

请注意,您应该很少使用 is,甚至更少使用 idid(foo) == id(bar) 总是错误的。


关于您的新示例,希望您明白它现在的作用:

>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True

在这种情况下,我们不会从类上的函数动态创建自动绑定 self 并返回绑定方法对象的方法。在这种情况下,您只需将函数存储为实例属性即可。查找时没有什么特别的事情发生(描述符仅在查找类属性时被调用),因此每次查找属性时,您都会获得存储的原始对象。

>>> b.test is a.test
False
>>> a.test is a.test
False

Methods are created on-the-fly each time you look them up. The function object (which is always the same object) implements the descriptor protocol and its __get__ creates the bound method object. No two bound methods would normally be the same object.

>>> id(a.test) == id(b.test)
True
>>> a.test is b.test
False

This example is deceptive. The result of the first is only True by coincidence. a.test creates a bound method and it's garbage collected after computing id(a.test) because there aren't any references to it. (Note that you quote the documentation saying that an id is "unique and constant for this object during its lifetime" (emphasis mine).) b.test happens to have the same id as the bound method you had before and it's allowed to because no other objects have the same id now.

Note that you should seldom use is and even less often use id. id(foo) == id(bar) is always wrong.


Regarding your new example, hopefully you get what it does now:

>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True

In this case, we aren't making methods on the fly from functions on the class automatically binding self and returning bound method objects. In this case, you simply store a function as an instance attribute. Nothing special happens on lookup (descriptors only get called when you look up a class attribute), so every time you look up the attribute, you get the original object you stored.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文