【问题标题】:python: problems with a list of class objects: All items are the same [duplicate]python:类对象列表的问题:所有项目都相同[重复]
【发布时间】:2012-04-05 04:53:39
【问题描述】:

可能重复:
“Least Astonishment” in Python: The Mutable Default Argument

我正在尝试从“fooclass”类创建一个具有不同属性的对象列表,但最终列表中的所有元素都包含相同的值。

这是我运行的代码:

#!/usr/bin/env python

class fooclass():
  def __init__(self,vertices = [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]):
    self.vertices = vertices

l=[]
print(l)
a=fooclass(); a.vertices[0]=[7,9,9]; l.append(a)
print 'a=', a.vertices
a=fooclass(); a.vertices[0]=[789,9,9]; l.append(a)
print 'a=', a.vertices
print(l[0].vertices)
print(l[1].vertices)
print(l)

l=[]
print(l)
a=fooclass(); a.vertices[0]=[7,9,9]; l.append(a)
print 'a=', a.vertices
b=fooclass(); b.vertices[0]=[789,9,9]; l.append(b)
print 'b=', b.vertices
print(l[0].vertices)
print(l[1].vertices)
print(l[0])
print(l[1])

我得到的输出:

$  python ./class_test2.py
[]
a= [[7, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
a= [[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[<__main__.fooclass instance at 0x7f945eafecf8>, <__main__.fooclass instance at 0x7f945eafed88>]
[]
a= [[7, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
b= [[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
<__main__.fooclass instance at 0x7f945eafecf8>
<__main__.fooclass instance at 0x7f945eafed88>

为什么输入不同的值,l[0].vertices 和 l[1].vertices 却完全一样?

系统信息:

Ubuntu 10.04.4 LTS
$  python --version
Python 2.6.5
$  uname -a
Linux *** 2.6.32-39-generic #86-Ubuntu SMP Mon Feb 13 21:50:08 UTC 2012 x86_64 GNU/Linux

注意:尝试使用 Python 3.1.2(只是更改打印语句),同样的问题。 :(

【问题讨论】:

  • 唉,又是mutable default argument...
  • 另外,从“object”继承你的类,或者当你需要更高级的类特性时受到令人讨厌的难以捉摸的行为。 (不从 object 继承的类是 Python 2 中的“旧式”类,不支持所有可用特性)
  • 感谢您的警告。只是对我所有的父类都这样做了(因为它似乎不适用于子类,我想它是从父类继承的)。

标签: python list class


【解决方案1】:

verticescan be modified in Python的默认值。您可以像这样重写__init__ 以避免它:

def __init__(self, vertices=None):
    if vertices is None:
        vertices = [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]
    self.vertices = vertices

【讨论】:

  • 谢谢。它使类更长(因为我有很多默认参数),但至少它有效。
【解决方案2】:

当您设置默认参数vertices = [...] 时,您实际上是在每次未指定参数时实例化一个要使用的列表对象。这意味着您的两个 fooclass 实例都在共享和修改一个列表。

如果没有为该参数指定值,则在您的__init__ 方法内部 将其实例化。这样可以确保每次运行该方法时都会创建一个新方法。

编辑: phihag 的回答给出了纠正__init__ 的很好的示例代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多