【问题标题】:assignment operator about list in PythonPython中关于列表的赋值运算符
【发布时间】:2012-10-05 00:09:48
【问题描述】:

我是Python初学者,对赋值运算符理解不清楚,例如:

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

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

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

谁能给点建议?

【问题讨论】:

  • 是的,list1[1] 可以被视为一个变量,但要确保列表实际上至少有两个元素。否则 Python 会报错索引 1 无法访问。

标签: python


【解决方案1】:

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

id() 可用于查看是否引用了 same 底层对象。

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

要创建已定义列表的副本,请使用 [:] 表示法,或 Matthew 提到的 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.)

【讨论】:

    【解决方案2】:

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

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

    此时 list1 和 list2 本质上都是对同一个可变列表的引用。当您更改该列表时,list1 和 list2 仍然引用相同的实际列表,并且使用其中任何一个来访问它都会得到相同的结果。

    我写了一篇关于相关主题 recently 的博文,而 Python Conques the Universe 也谈到了类似的主题 here

    【讨论】:

      【解决方案3】:

      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

      【讨论】:

        【解决方案4】:

        你是对的,它们不一样。在 Python (name = ...) 中对裸名称赋值是与对其他任何事物赋值不同的操作。特别是它不同于项目分配(name[0] = ...)和属性分配(name.attr = ...)。它们都使用等号,但后两者可以通过钩子(__setitem____setattr__)进行操作,可以调用任意代码,并且一般都在程序员的控制之下。对裸名称的分配不受 Python 程序员的控制。你不能影响它的作用;它总是将右侧绑定到左侧的名称。

        这可能会令人困惑,因为人们习惯于认为等号是构成“赋值”的原因。但是在 Python 中,为了了解正在发生的操作,您确实必须查看等号的左侧,看看分配给了什么样的东西。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-05-27
          • 1970-01-01
          • 2013-06-15
          • 2015-04-09
          • 2012-05-26
          • 1970-01-01
          • 1970-01-01
          • 2019-07-01
          相关资源
          最近更新 更多