微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为何熊猫在可迭代的情况下从`*`运算符创建浅拷贝?

如何解决为何熊猫在可迭代的情况下从`*`运算符创建浅拷贝?

这按预期工作:

a,b   = (0,) * 2
print('Before') 
print(a,b) 

a = 1
print('\nAfter')
print(a,b)

# Before
# 0 0
#
# After
# 1 0

它在熊猫中的作用不是,但是sb只是与sa相同系列的引用:

sa,sb = (pd.Series(np.zeros(2)),) * 2

print('Before')
for s in (sa,sb):
    print(s)

sa[0] = 1
print('\nAfter')
for s in (sa,sb):
    print(s)

# Before
# 0    0.0
# 1    0.0
# dtype: float64
# 0    0.0
# 1    0.0
# dtype: float64

# After
# 0    1.0
# 1    0.0
# dtype: float64
# 0    1.0          <- Note: sb[0] has also changed
# 1    0.0
# dtype: float64

这是否是预期的行为,是否已记录在案?它似乎违反了最小惊讶原则。

最方便的解决方法是什么?显然这可行:

sa = pd.Series(np.zeros(2))
sb = sa.copy() # note deep=True by default

但这有点冗长,因为我需要生成多个序列。

有效:

sa,sb = (pd.Series(np.zeros(2)).copy(),) * 2

解决方法

如上文《致癌基因》所述,熊猫系列是易变的,因此写给它们也可以修饰浅表。 dict可以看到相同的结果:

da,db = ({0:0,1:0},)*2
print('Before') 
for d in (da,db):
  print(d) 

da[0]=1
print('\nAfter') 
for d in (da,db):
  print(d) 

# Before
# {0: 0,1: 0}
# {0: 0,1: 0}

# After
# {0: 1,1: 0}
# {0: 1,1: 0} <- note: db has also changed

整数是不可变的,因此写入它们会破坏引用。这可以从变量地址中看到:

a,b   = (0,) * 2
print('Before') 
print(hex(id(a)),hex(id(b))) 

a = 1
print('\nAfter')
print(hex(id(a)),hex(id(b))) 

# Before
# 0x10ab9fef0 0x10ab9fef0

# After
# 0x10ab9ff10 0x10ab9fef0 <- first address changed

比较:

da,db):
  print(hex(id(d))) 

da[0]=1
print('\nAfter') 
for d in (da,db):
  print(hex(id(d))) 

# Before
# 0x137b9c320
# 0x137b9c320

# After
# 0x137b9c320 <- first address unchanged
# 0x137b9c320  

正如Henry Yik所说,从列表理解中分配是一种从可迭代对象(不同于*运算符)中创建深层副本的方法。

da,db = [pd.Series(np.zeros(2)) for _ in range(2)]
print('Before') 
for d in (da,db):
  print(hex(id(d))) 

# Before
# 0x137b9fad0 <- now it's different to begin with
# 0x137b93fd0

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?