Python:通过引用传递

时间:2016-03-30 23:40:24

标签: python

我想了解下面演示的行为。假设我们有简单的类

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的对象时(通过在此示例中再添加一列),我们将能够通过调用df2df2来查看修改后的对象,因为它们都指向同样的事情。

这是一个公平的理解吗?什么是最佳实践如果我们想要将两者分离?修改self.df而不影响df2。通过df或其他内容制作明确的副本?

1 个答案:

答案 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