我刚刚了解了Python中的类和用户定义函数,并且目前正在使用它们。
有时我很困惑输入的变量或实例属性是直接使用还是被复制为只在函数调用期间有效的局部变量。
例如:
class test1(object):
def __init__(self, a):
self.a = a
class test2(object):
def __init__(self, test):
self.a = test.a
self.add_d()
def add_d(self):
self.a += 'd'
print self.a
class test3(object):
def __init__(self, test):
self.fc = test
self.add_d()
def add_d(self):
self.fc.a += 'd'
print self.fc.a
和
In [36]: t = test1('abc')
In [37]: test2(t)
abcd
Out[37]: <__main__.test2 at 0xce5bcf98>
In [38]: t.a
Out[38]: 'abc'
没有从类test1更改实例“t”的属性“a”。
In [39]: test3(t)
abcd
Out[39]: <__main__.test3 at 0xfc3c9e8>
In [40]: t.a
Out[40]: 'abcd'
从类test1 更改实例“t”的属性“a”。
通常,我在几个场景中使用了函数:
旨在通过调用函数来改变(变异)输入变量。
返回值是函数调用所需的唯一内容,输入的变量应保持不变。
传递matplotlib的轴并在函数中排列绘图命令。 (这总是有效,永远不会出错。)
如果我对原始数据进行了不必要的更改,反之亦然,那将会非常麻烦。那么这里的基本概念是什么?另外,我们应该养成哪些习惯来防止这种错误?
答案 0 :(得分:1)
我认为您在问第二个示例中为什么test1
实例被修改但在第一个示例中没有被修改?
在第一个之后:
self.a = test.a
self.a
指的是test.a
,它是相同的不可变字符串对象。现在的时候:
self.a += 'd'
执行将表达式self.a + d
的值重新绑定到self.a
,即创建一个新的字符串对象。因为字符串是不可变的,所以不能更改原始字符串,因此必须创建新字符串。此时,a
对象中的属性test2
引用不同的对象,而不是a
对象中的test1
属性,该属性保持不变
在
之后的第二个例子中self.fc = test
self.fc
引用对象test
,它是变量t
引用的相同的对象。就变量引用而言,这与第一种情况相同,但不同之处在于此对象是可变的,所以
self.fc.a += 'd'
执行新字符串创建并绑定到对象的a
属性 - 但self.fc
仍然引用同一个对象。因此t.a
已更改。
我试图用你的例子来解释这一点。关键点在于Python变量引用了对象,并且可以有多个对同一对象的引用。可以通过任何引用变量对对象进行更改,无论使用哪个变量进行查看,都可以看到该更改。在赋值期间不会生成对象的副本,但是,如果创建新对象以便保留某些对象的不变性,则可以更改引用。