我看到了三个基本的Python概念,这些概念可以使您对该问题有所了解:
1)首先,来自可变对象的赋值
self.foo = arg1
就像复制一个指针(而不是指向的值)一样:self.foo和arg1是同一对象.这就是为什么接下来的那行
self.foo.age = 23
修改arg1(即Person1).因此,变量是不同的“名称”或“标签”,它们可以指向唯一的对象(在此为人员对象).这解释了为什么baz(Person1)将Person1.age和bar1.foo.age修改为27,因为Person1和bar1.foo只是同一个人对象的两个名称(Person1是bar1.foo在Python中返回True).
2)第二个重要概念是作业.在
def teh(arg1):
arg1 = [3,2,1]
变量arg1是局部的,因此代码
meh = [1,2,3]
teh(meh)
首先是arg1 = meh,这意味着arg1是列表meh的附加(本地)名称;但是执行arg1 = [3,2,1]就像说“我改变了主意:arg1从现在开始将成为新列表的名称[3,2,1]”.这里要记住的重要一点是,尽管分配以“等号”表示,但它们是不对称的:它们为右侧的(可变)对象赋予了一个额外的名称,在左侧为侧面(这就是为什么您不能执行[3,2,1] = arg1的原因,因为左侧必须是名称[或名称]).因此,arg1 = meh; arg1 = [3,2,1]无法更改meh.
3)最后一点与问题标题有关:“按值传递”和“按引用传递”不是Python中相关的概念.相反,相关概念是“可变对象”和“不可变对象”.列表是可变的,而数字不是可变的,这说明了您观察到的内容.同样,您的Person1和bar1对象是可变的(这就是为什么您可以更改此人的年龄).您可以在text tutorial和video tutorial中找到有关这些概念的更多信息.Wikipedia也具有一些(more technical) information.一个示例说明了可变和不可变之间的行为差??异:
x = (4, 2)
y = x # This is equivalent to copying the value (4, 2), because tuples are immutable
y += (1, 2, 3) # This does not change x, because tuples are immutable; this does y = (4, 2) + (1, 2, 3)
x = [4, 2]
y = x # This is equivalent to copying a pointer to the [4, 2] list
y += [1, 2, 3] # This also changes x, because x and y are different names for the same (mutable) object
最后一行不等于y = y [1、2、3],因为这只会将新的列表对象放在变量y中,而不是更改y和x引用的列表.
上面的三个概念(名称为[可变对象]的变量,不对称赋值和可变性/不可变性)解释了Python的许多行为.