通过组合旧数据结构的部分来构建数据结构时,Python是否总是进行浅拷贝?

When building datastructures by combining parts of old datastructures, does Python always do shallow copy?

如果我从列表中的一些现有元素创建一个新列表,python然后会将项目浅复制到新列表吗?

这里有一个代码示例来阐明我的意思:

structure = [] 
structure.append([pd.read_excel("df1.csv"), item1]) #contains a large dataframe, df1, and some other object, item1
structure.append([pd.read_excel("df2.csv"), item2]) #analoguous

lst = [structure[0][0]["some_column1"], structure[1][0]["some_column2"]] #here we save just the dataframe

当做其他类似的操作,从现有的数据结构中提取内容并将其插入新的数据结构(没有给出任何明确的指令来执行深拷贝)时,是否有某种规则,当 Python 将浅拷贝?或者在某些情况下会发生默认复制机制很深的情况吗?

Python 中的变量总是对堆上对象的引用(智能指针)。 Python 中没有像 C 中那样存在于堆栈中的对象的概念。在 Python 中为一个值分配一个新名称并不会复制它,它只是添加对对象的引用。

A Python 列表同样是这些引用的列表。将现有堆对象放入 Python 列表只是添加对它的引用。它不会复制它。 foo.copy() 方法或 foo[:] 完整切片(其中 foo 是一个列表)进行浅表复制。同样 list(foo)[*foo] 是浅拷贝。如果您需要的话,copy 模块中有一个深度复制功能。

数组的规则可能不同。 Pandas 数据帧基于 Numpy 数组。虽然这些可以包含指针(如字符串,它可以是可变长度),但它们也可以包含没有引用的行中的值,这对于数字数组来说是典型的。

这些类型的多维 Numpy 数组与列表的列表不同,不能浅复制,因为它们根本不包含指针。但是,与 Python 的内置集合不同,对 Numpy 数组进行切片通常会对同一数组进行 "view",但在某些情况下这是不可能的,Numpy 必须进行复制。

从这样的数组中获取值意味着将值复制为堆对象,以便 Python 可以直接引用它。当然,您可以通过将其分配给新变量或将其放入列表中来对整个数组进行新引用。但是,当然,这根本不是数组的副本。


So, just to confirm, that means that my lst is a deep copy of the parts of the pandas structures?

没有(可能)。您创建了一个新列表,但它(可能)包含对与数据框相同的列对象的引用,或者至少 "views" 相同。

除非您使用 inplace=True 参数(某些操作甚至不可用),否则 Pandas 中的大多数操作都会进行复制。当然,对索引的赋值是就地的,但要注意间接 chained indexing,它最终可能会分配给一个副本。

当通过索引获取时,Pandas 将 尝试 使用视图来提高效率,但是就像它所基于的 Numpy 数组一样,这并不总是可能的(比如当对象有多个数据类型时)。在不知道您的数据框结构的情况下,我无法确定哪个适用,甚至可能不适用,但我最好的猜测是浅拷贝。在简单情况之外很难预测,并且可能取决于碰巧选择的内存布局 Pandas,这是一个实现细节,如有更改,恕不另行通知。不要指望它。明确并使用复制方法。