>> s1 = -6ren">
gpt4 book ai didi

python - 为什么 float 对象与 "is"运算符的行为不同?

转载 作者:行者123 更新时间:2023-12-05 01:05:42 25 4
gpt4 key购买 nike

据我所知,cpython 实现为某些相同的值保留相同的对象以节省内存。例如,当我创建 2 个值为 hello 的字符串时,cpython 不会创建 2 个不同的 PyObject:

>>> s1 = 'hello'
>>> s2 = 'hello'
>>> s1 is s2
True

我听说它的名字是字符串实习。当我尝试用其他 python 类型检查它时,我观察到几乎所有可散列(不可变)类型都是相同的:

>>> int() is int()
True
>>> str() is str()
True
>>> frozenset() is frozenset()
True
>>> bool() is bool()
True

而且几乎所有的可变类型都是相反的(cpython 会创建一个新的 PyObject 甚至对于相同的值):

>>> list() is list()
False
>>> set() is set()
False
>>> dict() is dict()
False

我认为这是因为我们可以为不可变对象(immutable对象)使用相同的 PyObject 而不会出现任何问题。

当我看到 float 类型的行为与其他不可变类型不同时,我的问题就出现了:

>>> float() is float()
False

为什么不一样?

最佳答案

可变对象总是创建一个新对象,否则数据将被共享。这里没有太多要解释的,就好像你将一个项目附加到一个空列表中,你不希望所有的空列表都有那个项目。

不可变对象(immutable对象)的行为方式完全不同:

  • 字符串得到interned。如果它们小于 20 个字母数字字符,并且是静态的(代码中的常量、函数名等),它们会被缓存并从为它们保留的特殊映射中访问。它是为了节省内存,但更重要的是用于更快的比较。 Python 在后台使用了许多需要字符串比较的字典访问操作。能够通过比较它们的内存地址而不是实际值来比较属性或函数名称等 2 个字符串,这是一项显着的运行时改进。

  • 简单的 bool 值 return the same object .考虑到只有 2 个可用,一次又一次地创建它们是没有意义的。

  • 默认为小整数(-5 到 256),are also cached .这些经常使用,几乎无处不在。每次整数在该范围内时,CPython 都会简单地返回相同的对象。

但是, float 不会被缓存。与 0-10 非常常见的整数不同,1.0 不能保证比 2.00.1 更常用。这就是为什么 float() 只是简单地返回一个新的 float 。我们可以优化空的 float(),我们可以检查速度优势,但它可能不会产生这样的差异。

float(0.0) 是float(0.0) 时就会出现混淆。 Python 内置了许多优化:

  • 首先,常量保存在每个函数的代码对象中。 0.0 is 0.0 只是指同一个对象。这是一个编译时优化。

  • 其次,float(0.0) 采用 0.0 对象,因为它是一个 float (不可变),它 simply returns it .如果它已经是 float ,则无需创建新对象。

  • 最后,1.0 + 1.0 is 2.0 也可以。原因是 1.0 + 1.0 是在编译时计算的,然后引用相同的 2.0 对象:

    def test():
    return 1.0 + 1.0 is 2.0

    dis.dis(test)
    2 0 LOAD_CONST 1 (2.0)
    2 LOAD_CONST 1 (2.0)
    4 IS_OP 0
    6 RETURN_VALUE

    如您所见,没有加法运算。该函数被编译,结果指向完全相同的常量对象。

因此,虽然没有特定于 float 的优化,但有 3 种不同的通用优化正在发挥作用。它们的总和最终决定了它是否是同一个对象。

关于python - 为什么 float 对象与 "is"运算符的行为不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70452989/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com