我想了解下面演示的行为。假设我们有简单的类
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
的{{1}}属性(以及基础属性)现在也已更改。
a
我从广义上理解,它与Python参考设计中讨论得很多的传递有关,我怀疑这里的关键是a.df
c1 c2
r1 1 4
r2 2 5
r3 3 6
方法中的行df2=self.df
。因此summary
实际上是指向与df2
相同的内存位置的引用。因此,当我们修改标记为self.df
的对象时(通过在此示例中再添加一列),我们将能够通过调用df2
或df2
来查看修改后的对象,因为它们都指向同样的事情。
这是一个公平的理解吗?什么是最佳实践如果我们想要将两者分离?修改self.df
而不影响df2
。通过df
或其他内容制作明确的副本?
答案 0 :(得分:2)
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
可以解决您的问题,这是正确的,但这与按值传递或按引用传递无关,后者引用了参数函数调用,无论如何都没有准确地描述Python的函数调用语义。
对于你的情况,以及函数调用中的参数,最简单的心理图是Brett Cannon对粘性标签的想法。所有的名字,例如所谓的变量名称是引用实际对象的粘性标签。因此,您可以根据需要创建任意数量的粘性标签:
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.
关键字,您可以删除名称(即粘性标签),但只有在没有更多引用时才会删除基础对象。
^(?!.*(baz)).*exe