我正在试着理解下面的行为。假设我们有一个简单的类
class A():
def __init__(self):
self._df = pd.DataFrame([1,2,3], columns=['c1'], index=['r1', 'r2', 'r3'])
@property
def df(self):
return self._df
def summary(self):
df2 = self.df
df2['c2'] = pd.Series([4,5,6], index=df2.index)
return df2我们制作了一个实例a
a = A()然后a.df返回
c1
r1 1
r2 2
r3 3调用summary方法
s = a.summary()
s返回
c1 c2
r1 1 4
r2 2 5
r3 3 6到目前为止还不错。但是,对象df的a属性(和基础属性)现在也被更改了。
a.df
c1 c2
r1 1 4
r2 2 5
r3 3 6在广义上,我理解它与经过大量讨论的Python参考设计有关,我怀疑这里的关键是summary方法中的行summary。因此,df2实际上是指向与self.df相同的内存位置的引用。因此,当我们修改标记为df2的对象时(通过在本例中再添加一列),我们将能够通过调用df2或self.df来查看修改过的对象,因为它们都指向相同的东西。
这是一个公平的理解吗?如果我们想要将两者分离开来,最佳实践是什么?编辑df2而不影响df。通过df2 = self.df.copy()或其他什么方式复制一个显式副本?
发布于 2016-04-01 01:46:03
df2 = self.df.copy()可以解决您的问题,这是正确的,但这与按值传递或引用传递无关,它们都引用函数调用中的参数,而且这两种方法都不准确地描述函数调用的语义。
对于您的情况,以及函数调用中的参数,最简单的心理图片是Brett的粘性标签概念。所有的名称,例如所谓的变量名,都是引用实际对象的粘性标签.因此,您可以创建任意数量的粘性标签:
def f():
pass
g = h = k = m = f # You created 4 new sticky labels that refer to a single function
class A():
pass
g = h = k = m = A # Reusing same 4 labels, all refer to one class
a = ()
g = h = k = m = a # Reusing same 4 labels, all refer to one instance将标签(名称)重新分配到另一个对象,只意味着前面的对象丢失了一个引用。当对象没有引用时,它将被删除。在上面的示例中,我创建了对类A实例的一系列引用。使用del关键字,您可以删除名称(即粘性标签),但只有当没有对其的引用时,底层对象才会被删除。
del h
del k
del m
del a
# At this point, there is still one active reference to the instance
# that we first created when we assigned it to name "a".
del g
# Now we have removed all references to that instance, so it gets deleted.https://stackoverflow.com/questions/36321685
复制相似问题