id()与`is`运算符.比较`id`是否安全?相同的id是否代表相同的对象? [英] id() vs `is` operator. Is it safe to compare `id`s? Does the same `id` mean the same object?

查看:172
本文介绍了id()与`is`运算符.比较`id`是否安全?相同的id是否代表相同的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在实践中我可以在多大程度上依赖对象的id()及其唯一性?例如:

How much can I rely on the object's id() and its uniqueness in practice? E.g.:

  • id(a) == id(b)a is b还是相反?相反吗?
  • id保存在某个地方以便以后使用(例如,保存到某个注册表中而不是对象本身)有多安全?
  • Does id(a) == id(b) mean a is b or vice versa? What about the opposite?
  • How safe is it to save an id somewhere to be used later (e.g. into some registry instead of the object itself)?

(作为对推荐答案

根据 id()文档,只能保证id是唯一的

  1. 在特定对象的生命周期内,
  2. 在特定的解释器实例中

因此,比较id是不安全的,除非您还以某种方式确保在比较时两个被取为id的对象仍然存在(并且与相同的Python解释器实例,但您需要真正尝试使它变为假).

As such, comparing ids is not safe unless you also somehow ensure that both objects whose ids are taken are still alive at the time of comparison (and are associated with the same Python interpreter instance, but you need to really try to make that become false).

is正是这么做的-这使得比较id是多余的.如果出于某种原因不能使用is语法,则总是

Which is exactly what is does -- which makes comparing ids redundant. If you cannot use the is syntax for whatever reason, there's always operator.is_.

现在,在比较时对象是否还活着并不总是显而易见的(有时甚至很明显地不是-i):

Now, whether an object is still alive at the time of comparison is not always obvious (and sometimes is grossly non-obvious):

  • Accessing some attributes (e.g. bound methods of an object) creates a new object each time. So, the result's id may or may not be the same on each attribute access.

示例:

>>> class C(object): pass
>>> c=C()
>>> c.a=1

>>> c.a is c.a
True        # same object each time

>>> c.__init__ is c.__init__
False       # a different object each time

# The above two are not the only possible cases.
# An attribute may be implemented to sometimes return the same object
# and sometimes a different one:
@property
def page(self):
    if check_for_new_version():
        self._page=get_new_version()
    return self._page

  • 如果对象是由于计算表达式而创建的,并且没有保存在任何地方,则将其立即丢弃 1 ,此后创建的任何对象都可以id.

  • If an object is created as a result of calculating an expression and not saved anywhere, it's immediately discarded,1 and any object created after that can take up its id.

    • 在同一代码行中甚至如此.例如. id(create_foo()) == id(create_bar())的结果不确定.

    示例:

    >>> id([])     #the list object is discarded when id() returns
    39733320L
    >>> id([])     #a new, unrelated object is created (and discarded, too)
    39733320L      #its id can happen to be the same
    >>> id([[]])
    39733640L      #or not
    >>> id([])
    39733640L      #you never really know
    

  • 由于比较id时的上述安全要求,保存id而不是对象不是很有用,因为无论如何您都必须保存对对象本身的引用-以确保它保持生命.也不会有任何性能提升: is实现非常简单作为比较指针.

    Due to the above safety requirements when comparing ids, saving an id instead of the object is not very useful because you have to save a reference to the object itself anyway -- to ensure that it stays alive. Neither is there any performance gain: is implementation is as simple as comparing pointers.

    最后,作为内部优化(和实现细节,因此实现和发行版之间可能会有所不同),CPython重用了一些经常使用的不可变类型的简单对象.在撰写本文时,其中包括小整数

    Finally, as an internal optimization (and implementation detail, so this may differ between implementations and releases), CPython reuses some often-used simple objects of immutable types. As of this writing, that includes small integers and some strings. So even if you got them from different places, their ids might coincide.

    (在技术上)这没有违反上述id()文档的唯一性保证:重用的对象在所有重用中都保持活动状态.

    This does not (technically) violate the above id() documentation's uniqueness promises: the reused object stays alive through all the reuses.

    这也没什么大不了的,因为两个变量是否指向同一个对象只知道该对象是否可变:

    This is also not a big deal because whether two variables point to the same object or not is only practical to know if the object is mutable: if two variables point to the same mutable object, mutating one will (unexpectedly) change the other, too. Immutable types don't have that problem, so for them, it doesn't matter if two variables point to two identical objects or to the same one.

    1 有时,这称为未命名表达式".

    这篇关于id()与`is`运算符.比较`id`是否安全?相同的id是否代表相同的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆