【问题标题】:Python '==' operator gives wrong resultPython '==' 运算符给出错误结果
【发布时间】:2021-04-18 19:55:18
【问题描述】:

我正在比较一个 numpy 数组的两个元素。 id() 函数为两个元素获取的内存地址不同。此外,is 运算符表明这两个元素不相同。

但是,如果我使用 == 运算符比较两个数组元素的内存地址,则会发现这两个元素是相同的。

当两个内存地址不同时,我无法理解== 运算符如何将输出输出为True

下面是我的代码。

import numpy as np

a = np.arange(8)
newarray = a[np.array([3,4,2])]

print("Initial array : ", a)
print("New array : ", newarray)

# comparison of two element using 'is' operator
print("\ncomparison using is operator : ",a[3] is newarray[0])

# comparison of memory address of two element using '==' operator
print("comparison using == opertor : ", id(a[3]) == id(newarray[0]))

# memory address of both elements of array
print("\nMemory address of a : ", id(a[3]))
print("Memory address of newarray : ", id(newarray[0]))

输出:

初始数组:[0 1 2 3 4 5 6 7]
新数组:[3 4 2]

使用is 运算符比较:False
使用== 运算符进行比较:True

a的内存地址:2807046101296
newarray的内存地址:2808566470576

【问题讨论】:

    标签: arrays python-3.x numpy operators deep-copy


    【解决方案1】:

    这可能是由于Python's integer cachingnumpy 的模糊实现细节的结合。

    如果你稍微改变一下代码,你会发现ids 在代码运行过程中并不一致,但实际上每一行都是一样的:

    import numpy as np
    
    a = np.arange(8)
    newarray = a[np.array([3,4,2])]
    print(id(a[3]), id(newarray[0]))
    print(id(a[3]), id(newarray[0])) 
    

    输出

    276651376 276651376
    20168608 20168608
    

    【讨论】:

      【解决方案2】:

      numpy 数组不会像列表那样存储对对象的引用(除非它是对象dtype)。它有一个带有数值的一维数据缓冲区,它可以通过各种方式访问​​。

      In [17]: a = np.arange(8)
          ...: newarray = a[np.array([3,4,2])]
      In [18]: a
      Out[18]: array([0, 1, 2, 3, 4, 5, 6, 7])
      In [21]: newarray
      Out[21]: array([3, 4, 2])
      

      newarray,使用高级索引生成的不是view。它有自己的数据缓冲区和值。

      让我们“拆箱”这些数组的元素,将它们分配给变量。

      In [22]: x = a[3]; y = newarray[0]
      In [23]: x
      Out[23]: 3
      In [24]: y
      Out[24]: 3
      In [25]: id(x),id(y)
      Out[25]: (139768142922768, 139768142925584)
      

      id 不同(分配防止了可能混淆的 id 回收)。

      id 不同,所以isFalse

      In [26]: x is y
      Out[26]: False
      

      但值相同(通过 == 测试)

      In [27]: x == y
      Out[27]: True
      

      另一个“拆箱”,不同的 id:

      In [28]: w = a[3]
      In [29]: w
      Out[29]: 3
      In [30]: id(w)
      Out[30]: 139768133495504
      

      这些整数实际上是np.int64 对象。 Python 会“缓存”小整数,但这不适用于此处。

      In [33]: type(x)
      Out[33]: numpy.int64
      

      在哪里可以看到数组存储数据的“位置”:

      In [31]: a.__array_interface__['data']
      Out[31]: (33696480, False)
      In [32]: newarray.__array_interface__['data']
      Out[32]: (33838848, False)
      

      这些是完全不同的缓冲区。如果newarrayview,则缓冲区指针将相同或相近。

      如果我们不挂在被索引的对象上,ids 可能会被重用:

      In [34]: id(newarray[0]), id(newarray[0])
      Out[34]: (139768133493520, 139768133493520)
      

      一般isid 在处理numpy 数组时没有用处。

      【讨论】:

        猜你喜欢
        • 2021-02-13
        • 1970-01-01
        • 2017-11-18
        • 1970-01-01
        • 2013-06-01
        • 1970-01-01
        • 2018-02-09
        • 2012-08-30
        • 1970-01-01
        相关资源
        最近更新 更多