“a is b”和“a is b”有什么区别?和“id(a)==id(b)”在Python中?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
每次查找方法时都会即时创建方法。函数对象(始终是同一个对象)实现描述符协议 及其
__get__
创建绑定方法对象。通常没有两个绑定方法是同一个对象。这个例子是骗人的。第一个结果为
True
纯属巧合。a.test
创建一个绑定方法,并在计算id(a.test)
后对其进行垃圾回收,因为没有任何对其的引用。 (请注意,您引用的文档说 id 是“该对象在其生命周期内是唯一且恒定的”(强调我的)。)b.test
发生 与之前的绑定方法具有相同的 id,这是允许的,因为现在没有其他对象具有相同的 id。请注意,您应该很少使用
is
,甚至更少使用id
。id(foo) == id(bar)
总是错误的。关于您的新示例,希望您明白它现在的作用:
在这种情况下,我们不会从类上的函数动态创建自动绑定 self 并返回绑定方法对象的方法。在这种情况下,您只需将函数存储为实例属性即可。查找时没有什么特别的事情发生(描述符仅在查找类属性时被调用),因此每次查找属性时,您都会获得存储的原始对象。
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.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 computingid(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 useid
.id(foo) == id(bar)
is always wrong.Regarding your new example, hopefully you get what it does now:
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.