赋值运算符关于Python中的列表

时间:2012-10-15 02:23:12

标签: python

我是Python的初学者,我无法清楚地理解赋值运算符,例如:

list1 = ["Tom", "Sam", "Jim"]
list2 = list1

以上两个语句将'list1'和'list2'绑定到["Tom", "Sam", "Jim"],问题是, 如果是下面的运营商:

list1[1] = "Sam's sister",如果赋值语句也被视为绑定,那么list2[1]仍然与“Sam”相关联,结果是修改list1不会影响{{ 1}},即使Python呈现相反的输出,另一个问题是list2是否可以被视为Python中的list1[1]list1变量。

任何人都可以有任何建议吗?

4 个答案:

答案 0 :(得分:4)

在您的示例中,标识符list1list2是对同一底层对象的引用(只是同一事物的不同名称)。

id()可用于查看是否正在引用相同的底层对象。

>>> list1 = ["Tom", "Sam", "Jim"]
>>> list2 = list1
>>> id(list1)
44259368
>>> id(list2)
44259368

要创建已定义列表的副本,请使用[:]表示法,或马修所提到的deepcopy。您会注意到,完成此操作后,位置/ ID已更改。

>>> list3 = list1[:]
>>> id(list3)
44280208

关于id命令:

>>> help(id)
Help on built-in function id in module __builtin__:

id(...)
    id(object) -> integer

    Return the identity of an object.  This is guaranteed to be unique among
    simultaneously existing objects.  (Hint: it's the object's memory address.)

答案 1 :(得分:3)

你是对的,他们不一样。在Python中分配一个裸名称(name = ...)与分配给其他任何东西的操作不同。特别是它与项目分配(name[0] = ...)和属性分配(name.attr = ...)不同。它们都使用等号,但后两个可以用钩子(__setitem____setattr__)操纵,可以调用任意代码,并且通常在程序员的控制之下。对裸名称的赋值不受Python程序员的控制。你无法影响它的作用;它总是将右侧与左侧的名字绑在一起。

这可能令人困惑,因为人们习惯于认为等号是做出“任务”的原因。但是在Python中,为了理解正在进行的操作,你必须查看等号的左边,看看是什么类型的东西。

答案 2 :(得分:1)

BrenBarn对所有事情都是绝对正确的,但这是另一种看待它的方式,可能更容易理解:

您的第一个语句创建一个包含这些值的列表,然后使list1指向它。第二个语句使list2指向与list1完全相同的内存空间。 (你可以通过在第二个语句之后在它们上面运行id来看到这一点)。

此时,list1和list2基本上都是对同一可变列表的引用。当您更改该列表时,list1和list2仍然引用相同的实际列表,并且使用它们访问它将为您提供相同的功能。

我做了一篇关于相关主题的博客文章recently和Python Conquers the Universe也讨论了类似主题here

答案 3 :(得分:0)

BrenBam对正在发生的事情有一个很好的解释。 deepcopy一种解决问题的方法:

>>> from copy import deepcopy
>>> list1 = ["Tom", "Sam", "Jim"]
>>> list2 = deepcopy(list1)
>>> list1[1] = "Sam's sister"
>>> list1
['Tom', "Sam's sister", 'Jim']
>>> list2
['Tom', 'Sam', 'Jim']

良好的编程风格使得实际使用deepcopy的情况很少见。