【问题标题】:Python: 'inf is inf', but '-inf is not -inf'?Python:'inf 是 inf',但 '-inf 不是 -inf'?
【发布时间】:2020-07-15 18:47:45
【问题描述】:

Python 3.7

在编写最大值的搜索代码时,我遇到了负无穷大的奇怪行为。 有人可以解释为什么会出现这种行为吗?

>>> inf = float('inf')
>>> inf is inf
True
>>> (-inf) is (-inf)
False

我已经意识到最好使用== 进行比较,但我对上述问题的答案很感兴趣。

【问题讨论】:

  • 嗯,好像——当否定时,它创建了一个不同的对象,而不是改变现有的对象。 @chepner 已经回答了。

标签: python python-3.x infinity


【解决方案1】:

inf 是一个变量,绑定到一个特定的对象。任何对象is 本身,所以inf is inf

-inf 是一个表达式。它进行数学运算,并生成一个值浮点负无穷大的对象。 Python 没有承诺 this 是否与具有该值的任何其他对象相同。在您的情况下,-inf 的两次评估碰巧产生了不同的对象。

同样,对于-inf is -inf 将产生什么,没有任何承诺。当前的 CPython 实现恰好始终产生 False。 PyPy 的原始处理produces True。不同的 Python 版本或实现可能会根据当前的内存压力不一致地产生 True 或 False,或者您是否将其作为脚本或交互方式运行,或任何其他因素。 CPython 本身已经存在对象标识在脚本中或交互方式中不同的情况;例如,这个:

x = 1000
y = 1000
print(x is y)

根据您是否以交互方式运行,在当前 CPython 实现中打印不同的内容。

【讨论】:

  • 好的,我明白了。谢谢。这也是因为名字不好(inf 数字和inf 变量)。在这种情况下,最好将负无穷大分开:python inf = float('inf'); ninf = -inf; ninf is ninf
  • @ДаниилКонягин:只是不要将is 用于浮动。这是错误的比较。
  • 是的,我也想通了。
【解决方案2】:

-inf 是一个产生新的float 对象的操作,您在同一个表达式中使用它两次。生成了两个不同的对象,因为 Python 实现不需要注意两个子表达式可以返回对同一对象的引用。

【讨论】:

    【解决方案3】:

    我想补充一点:在 Python 中,当我们使用id() 函数、is 运算符、== 运算符等时,我们正在使用的真正目标是 value ,而不是变量

    a is b 等于 id(a) == id(b)

    在您的代码中,inf = float('inf') 将生成一个名为 inf 的值。

    inf 也是一个表达式,将被计算为一个值。

    inf is inf 将是True,因为实际上两个表达式的计算值是相同的。

    在 Python 中,专注于价值观会更好、更容易。

    例如,在 CPython 实现中:

    a = 1
    b = 1
    a is b # will be true
    
    a = 10000
    b = 10000
    a is b # will be false
    
    a = '10000'
    b = '10000'
    a is b # will be true
    

    如果我们专注于变量,这样的事情很奇怪。如果我们专注于值,如果我告诉你 CPython 实现有缓存池,它用于小 int 和一些文字 str 值,那么事情就又简单了:

    因为缓存池,small int 1被缓存了,str '10000'也被缓存了,但是big int 10000没有被缓存,所以会被创建两次。

    尝试专注于价值观。

    【讨论】: