这是一个错误吗?不能简单地将 dict 键从 numpy 更改为原始数据类型

Is this a bug? Cannot simply change dict keys from numpy to primitive data types

我有一个由 pandas 生成的字典,它有 numpy.int64 个对象而不是本机 int 作为键。我需要将它们更改为本机类型,并且对为什么以下代码不是那么成功感到困惑:

d = {np.int64(0): None}

for k, v in d.items():
    print(str(type(k)))     # <class 'numpy.int64'>
    k_nat = k.item()
    print(str(type(k_nat))) # <class 'int'>
    print(d)                # {0: None}
    d.update({k_nat:1})
    print(d)                # {0: 1}
                            # Therefore update using int was successful

for k, v in d.items():
    print(str(type(k)))     # <class 'numpy.int64'>

谁能解释一下这是怎么回事?从我的角度来看,这段代码自相矛盾,因为使用原语 k_nat 的更新是成功的,但最终密钥仍然是 numpy.int64.

不,这不是错误。

这段代码表明密钥在更新期间没有改变:

import numpy as np
d = {np.int64(0): None}

for k, v in d.items():
    print(str(type(k)))     # <class 'numpy.int64'>
    k_nat = k.item()
    print(str(type(k_nat))) # <class 'int'>
    print(d)                # {0: None}
    d.update({k_nat:1})
    print(d)                # {0: 1}
                            # Therefore update using int was successful
                            # But key does not change
    print(type(list(d.keys())[0])) # → <class 'numpy.int64'>

for k, v in d.items():
    print(str(type(k)))     # <class 'numpy.int64'>

Python 对待 int(0)np.int64(0) w.r.t。 dict-access。但是原始键没有改变(只有值)。请注意,int(0)np.int64(0)print(d) 等表达式中都表示为 0。所以他们 看起来 就像他们一样。但是,它们相等但不相同

特别是我们有这种行为

print(d[np.int64(0)] == d[int(0)]) # True
print(np.int64(0) == int(0)) # True
print(np.int64(0) is int(0)) # False

如果要转换key-type,可以使用:

new_d = {int(k): v for k, v in d.items()}
print(type(list(new_d.keys())[0])) # <class 'int'>

对于 some 类 确实可以在不改变对象的 id 的情况下改变对象的类型,因此它仍然可以作为同样的 dict-key:

class A(object):
    pass

class B(object):
    pass

d = {A(): None}

print(type(list(d.keys())[0])) # <class '__main__.A'>

# change type of object but not the object itself
list(d.keys())[0].__class__ = B
print(type(list(d.keys())[0])) # <class '__main__.B'>

然而,对于其他类(包括np.int64)这是不可能的:

x = np.int64(0)
try: 
    x.__class__ = int
except TypeError as err:
    print(err) # __class__ assignment only supported for heap types or ModuleType subclasses

0np.int64(0) 哈希到相同的值:

print(hash(0))
print(np.int64(0))

输出:

0
0

所以你的字典实际上并没有替换 keys 数据类型,你可以使用简单的字典理解来实现你想要的行为(在任何情况下修改一个可迭代的同时循环它可能不是一个好主意)

import numpy as np
d = {np.int64(0): None}

for k, v in d.items():
    print(str(type(k)))     # <class 'numpy.int64'>

d = {int(k):v for k,v in d.items()}
print(d)
for k, v in d.items():
    print(str(type(k)))

不过,根据您实际获取字典的方式,您最好直接更改 pandas series/dataframe

的数据类型