当前位置: 首页 > 面试题库 >

id()与`is`运算符。比较`id`是否安全?相同的id是否代表相同的对象?

佟阳焱
2023-03-14
问题内容

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

  • 是否id(a) == id(b)意味着a is b反之亦然?那相反呢?
  • 保存某个id地方以后使用(例如,放入某个注册表而不是对象本身)有多安全?

(作为针对Python规范的建议规范编写:是具有相同id()相同对象的对象,是is运算符,未绑定方法对象)


问题答案:

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

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

因此,
比较ids是不安全的,除非您还以某种方式确保在比较时两个id被s占用的对象仍然处于活动状态(并且与同一Python解释器实例相关联,但是您需要真正尝试使其变为false)
)。

正是这样is做的-
这使得比较ids是多余的。如果您is由于某种原因而无法使用语法,那么总会有operator.is_

现在, 一个物体是否还活着,在比较时并不总是显而易见的 (有时是极 -obvious):

  • **每次 访问某些属性 (例如,对象的绑定方法) 都会创建一个新对象。 因此,id每个属性访问的结果可能相同也可能不同。

例:

    >>> 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

    • 在同一代码行中甚至是这样。例如,结果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

由于比较ids时的上述安全性要求,因此用aid代替对象不是很有用,因为无论如何您都必须保存对对象本身的引用-
以确保它保持活动状态。也没有任何性能提升:is实现就像比较指针一样简单。

最后,作为内部优化(和实现细节,因此实现和发行版之间可能会有所不同),CPython重用了一些经常使用的不可变类型的简单对象。在撰写本文时,其中包括小整数和一些字符串。因此,即使您从不同的地方获得它们,它们的ids也会重合。

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

这也不是什么大问题,因为两个变量是否指向同一个对象只知道该对象是否可变:如果两个变量指向同一个可变对象,那么改变一个变量(意外地)也会改变另一个变量。不可变类型没有这个问题,因此对于它们来说,两个变量指向两个相同的对象还是指向同一对象都没有关系。

1有时,这称为“未命名表达式”。



 类似资料:
  • 两个 NavigableString 或 Tag 对象具有相同的HTML或XML结构时, Beautiful Soup就判断这两个对象相同. 这个例子中, 2个 <b> 标签在 BS 中是相同的, 尽管他们在文档树的不同位置, 但是具有相同的表象: “<b>pizza</b>” markup = "<p>I want <b>pizza</b> and more <b>pizza</b>!</p>"

  • 两个 NavigableString 或 Tag 对象具有相同的HTML或XML结构时, Beautiful Soup就判断这两个对象相同. 这个例子中, 2个 <b> 标签在 BS 中是相同的, 尽管他们在文档树的不同位置, 但是具有相同的表象: “<b>pizza</b>” markup = "<p>I want <b>pizza</b> and more <b>pizza</b>!</p>"

  • 问题内容: Java是强静态转换,因此这意味着“ ===”没有用处 我看了很多文档,但没有看过相同比较运算符。 问题答案: 在弱类型语言(例如Javascript)中非常有用,因为它可以验证被比较的对象是同一类型,并避免隐式转换。 在Java之类的强类型语言中绝对没有用,因为您不能在不编写特定方法的情况下比较不同类型的变量。 例如,如果你想一个比一个的,你将不得不写一些特殊的方法,例如: 但这几乎

  • 问题内容: 。 我有下表: 我需要用计算所有行。可能与聚合有关吗? 现在,我按如下操作: 问题答案: 如果您只需要对1的行数进行计数,则可以执行以下操作: 如果要计算 每 行的行数,则需要使用:

  • 本文向大家介绍什么是MySQL NULL安全相等运算符,它与比较运算符有何不同?,包括了什么是MySQL NULL安全相等运算符,它与比较运算符有何不同?的使用技巧和注意事项,需要的朋友参考一下 与标准SQL IS NOT DISTINCT FROM运算符等效的MySQL NULL安全相等运算符执行等于运算符的相等比较。其符号为<=>。当我们两个操作数都为NULL时,它的性能与比较运算符不同。请看

  • 我们的测试在一些目录中存储关于每个已执行测试的大量信息。如果同一次运行的所有结果都存储在一个以日期/id命名的目录中,这将是切实可行的。这样可以很容易地查看历史记录并跟踪是什么。目前这是一个手动作业,每次运行后都必须重命名输出目录以保留记录。 我们可以很容易地在cucumber之外编写脚本以实现自动化,但是我想知道这是否可以通过cucumber框架实现。一种简单的方法(如果可能的话)是创建一个ru