您没有获得“单元格”的ID,而是获得id
了.loc
访问器返回的对象的ID,该访问器是基础数据的盒装版本。
所以,
>>> import pandas as pd
>>> df = pd.DataFrame(columns=list('abc'), data=np.arange(18).reshape(6, 3))
>>> df1 = df.iloc[:3, :]
>>> df.dtypes
a int64
b int64
c int64
dtype: object
>>> df1.dtypes
a int64
b int64
c int64
dtype: object
但是由于Python中的 所有内容 都是对象,因此您的loc
方法必须返回一个对象:
>>> x = df.loc[0, 'a']
>>> x
0
>>> type(x)
<class 'numpy.int64'>
>>> isinstance(x, object)
True
但是,实际的基础缓冲区是C个固定大小的64位有符号整数的原始数组。它们不是Python对象,它们被“装箱”以从其他将原始类型与对象混合在一起的语言中借用一个术语。
现在,所有对象都具有相同现象的现象id
:
>>> id(df.loc[0, 'a']), id(df.loc[0, 'a'])
(4539673432, 4539673432)
>>> id(df.loc[0, 'a']), id(df.loc[0, 'a']), id(df1.loc[0,'a'])
(4539673432, 4539673432, 4539673432)
发生是因为在Python中,对象可以自由地重用最近回收的对象的内存地址。确实,当您创建的元组时id
,对象的返回loc
仅存在足够长的时间,以通过第一次调用进行传递和处理id
,第二次使用时loc
,已经释放的对象仅会重复使用相同的内存。您可以在任何Python对象中看到相同的行为,例如list
:
>>> id([]), id([])
(4545276872, 4545276872)
从根本上讲,id
只能保证在对象的 生存期内 唯一的。在此处阅读有关此现象的更多信息。但是请注意,在以下情况下,它将始终是不同的:
>>> x = df.loc[0, 'a']
>>> x2 = df.loc[0, 'a']
>>> id(x), id(x2)
(4539673432, 4539673408)
由于您维护引用,因此不会回收对象,并且需要新的内存。
注意,对于许多不可变的对象,解释器可以自由优化并返回 相同的精确对象 。在cpython中,“小整数”就是这种情况,所谓的小整数缓存:
>>> x = 2
>>> y = 2
>>> id(x), id(y)
(4304820368, 4304820368)
但这是不应该依赖的实现细节。
如果您想证明自己的数据帧正在共享相同的基础缓冲区,只需对其进行突变,便会在视图之间看到相同的变化:
>>> df
a b c
0 0 1 2
1 3 4 5
2 6 7 8
3 9 10 11
4 12 13 14
5 15 16 17
>>> df1
a b c
0 0 1 2
1 3 4 5
2 6 7 8
>>> df.loc[0, 'a'] = 99
>>> df
a b c
0 99 1 2
1 3 4 5
2 6 7 8
3 9 10 11
4 12 13 14
5 15 16 17
>>> df1
a b c
0 99 1 2
1 3 4 5
2 6 7 8