Python 我应该何时使用.copy()

Python 我应该何时使用.copy(),python,numpy,Python,Numpy,我知道,由于以下原因: a=1 b=a a=4 它将1分配给a,然后a分配给b,最后一步是将a的值更改为4。 此处,一旦a的值更改为4,则b的值将不会有任何更改 同样适用于 a=np.array([10,20,30,40,50,60]) b=a[2] a[2]=100 代码末尾的b值将为20,这是初始a[2] 但当你有一些事情,如下面所述: a=np.array([10,20,30,40,50,60]) b=a[0:2] 如果我们改变a[0:2]=[100200],那么b的值也会自动改变

我知道,由于以下原因:

a=1
b=a
a=4
它将
1
分配给
a
,然后
a
分配给
b
,最后一步是将
a
的值更改为
4

此处,一旦
a
的值更改为
4
,则
b
的值将不会有任何更改

同样适用于

a=np.array([10,20,30,40,50,60])
b=a[2]

a[2]=100
代码末尾的
b
值将为
20
,这是初始
a[2]

但当你有一些事情,如下面所述:

a=np.array([10,20,30,40,50,60])
b=a[0:2]
如果我们改变
a[0:2]=[100200]
,那么
b
的值也会自动改变。这就像变量
b
以某种方式链接到其他变量(与前面的情况不同)。
我知道如果代码写为
b=a[0:2].copy()
,那么即使
a
发生了变化,
b
也不会改变

因此,我的问题是,如果我不想更改后一个变量,因为在前两种情况下不需要它,那么我应该在哪里使用这个
.copy()
方法呢


感谢您的帮助

在第一种和第二种情况下,您为
b
指定了一个值(标量)

在第三种情况下,您已根据
a
的切片
0:2
将a分配给
b
(请参阅)。这本质上是对
a
的某些元素的多值引用(即:
b[0]
实际上是指
a[0]
)。换句话说,
b
并不拥有它的数据,而是指向
a
中的数据。因此,当更改
a
时,
b
仅反映这些更改,因为它指向的元素非常相同

通常,如果要将副本与原始副本分离,应使用numpy
copy()
,例如:

  • 当您准备对副本进行修改时(例如,偷偷改变调用方的数据并不酷)
  • 当您希望在该点保留阵列的快照时,无论以后原始阵列发生什么情况
  • 当您使用非常稀疏的切片或随机顺序,并且希望获得更紧凑的副本以实现更快的操作(参考位置)时
  • 当您想更改
    a
    b
    的标志时(例如,从C连续到F连续,通常也是出于速度原因)
  • 关于您在评论中提出的问题,“是否有任何方法可以确定变量是否相互关联”:是的。每个numpy数组都有
    标志

    a=np.array([10,20,30,40,50,60])
    b=a[2]
    b.flags.owndata
    # True  -- funny given that b is a single numpy.int64, but it still has flags
    
    b=a[0:2]
    b.flags.owndata
    # False
    
    a=np.array([10,20,30,40,50,60])
    b=a[0:2].copy()
    b.flags.owndata
    # True
    

    在第一种和第二种情况下,您为
    b
    指定了单个值(标量)

    在第三种情况下,您已根据
    a
    的切片
    0:2
    将a分配给
    b
    (请参阅)。这本质上是对
    a
    的某些元素的多值引用(即:
    b[0]
    实际上是指
    a[0]
    )。换句话说,
    b
    并不拥有它的数据,而是指向
    a
    中的数据。因此,当更改
    a
    时,
    b
    仅反映这些更改,因为它指向的元素非常相同

    通常,如果要将副本与原始副本分离,应使用numpy
    copy()
    ,例如:

  • 当您准备对副本进行修改时(例如,偷偷改变调用方的数据并不酷)
  • 当您希望在该点保留阵列的快照时,无论以后原始阵列发生什么情况
  • 当您使用非常稀疏的切片或随机顺序,并且希望获得更紧凑的副本以实现更快的操作(参考位置)时
  • 当您想更改
    a
    b
    的标志时(例如,从C连续到F连续,通常也是出于速度原因)
  • 关于您在评论中提出的问题,“是否有任何方法可以确定变量是否相互关联”:是的。每个numpy数组都有
    标志

    a=np.array([10,20,30,40,50,60])
    b=a[2]
    b.flags.owndata
    # True  -- funny given that b is a single numpy.int64, but it still has flags
    
    b=a[0:2]
    b.flags.owndata
    # False
    
    a=np.array([10,20,30,40,50,60])
    b=a[0:2].copy()
    b.flags.owndata
    # True
    

    您的问题是针对
    numpy
    (它有非标准的切片机制)还是一般的Python(切片几乎总是一个浅拷贝,这是我所知道的
    memoryview
    类型的内置版本中唯一的例外)。我假设是前者(让您困惑的行为在很大程度上是
    numpy
    和基于它的包所独有的),但是
    .copy()
    是一种针对许多类型的方法,目前还不清楚。我会注意到:规则将始终取决于所涉及的类型;切片没有保证的行为,因此您需要知道该类型的规则。@ShadowRanger感谢您的回复。因此,如果我们关注
    numpy
    。。。在我的第二个示例中,这是一个numpy数组,它不会影响变量
    b
    。但在第三种情况下,确实如此。因此,您能否建议一种适当的方法来确定变量是否链接。您的问题是针对
    numpy
    (它具有非标准的切片机制)还是针对一般的Python(切片几乎总是一个浅拷贝,这是我所知道的
    memoryview
    类型的内置中唯一的例外)。我假设是前者(让你困惑的行为主要是
    numpy
    和基于它的包所特有的),但是
    .copy()
    是一种适用于太多类型的方法,目前尚不清楚。我要注意:规则始终取决于所涉及的类型;切片没有保证的行为,因此您需要知道该类型的规则是什么。@ShadowRanger感谢您的回答。因此,如果我们关注
    numpy
    …在我的第二个示例中,这是一个numpy数组,它确实如此不影响变量
    b
    。但在第三种情况下,它会影响。因此,您能否建议一种适当的方法来确定变量是否链接。这是错误的“
    b
    ,作为浅拷贝,也会受到影响。”
    b
    不是浅拷贝;如果