代码之家  ›  专栏  ›  技术社区  ›  glibdud

实例属性意外加载[重复]

  •  0
  • glibdud  · 技术社区  · 14 年前

    我去年学了Python,刚开始做一个新项目。我一开始就遇到了一个障碍,在仔细阅读了一堆文档后,我仍然感到困惑。我不得不相信这是一件简单的事情,但我找不到。问题是:

    我在一个文件中设置了以下内容:

    class Wrapper(object):
        def __init__(self, title=None):
            self.header = Thing("HEADER")
            if title is not None:
                self.header.content.append( Thing("TITLE", content=[str(title)]) )
            self.body = Thing("BODY")
            self.content = Thing("COMPLETE", content=[self.header, self.body])
    
    class Thing(object):
        def __init__(self, name, content=[]):
            self.name = name
            self.content = content
    

    然后在交互式提示中,我会:

    >>> import things
    >>> a = things.Wrapper("This is a title")
    

    现在,我希望在这一点上 body 的属性 a 将是一个 Thing 具有名称的实例 "BODY" content 由一个空列表组成。我惊讶地发现 所容纳之物 实际上是一个包含相同内容的列表 "TITLE" 例如 a.header.content 持有。

    >>> a.header.name
    'HEADER'
    >>> a.header.content
    [<test.Thing object at 0xb752290c>]
    >>> a.body.name
    'BODY'
    >>> a.body.content
    [<test.Thing object at 0xb752290c>]
    >>> a.body.content[0].name
    'TITLE'
    >>> a.body.content[0].content
    ['This is a title']
    

    我一辈子都想不出该怎么做 a.body.content 是这样分配的。有人能解释一下吗?

    1 回复  |  直到 9 年前
        1
  •  1
  •   Ryan Haining    14 年前

    试试这个

    class Thing(object):
        def __init__(self, name, content=None):
            if content is None:
                content = []
            self.name = name
            self.content = content
    

    []作为默认值的问题是,当解释器第一次创建函数时,默认参数只计算一次。对于 int 或其他 不变的 键入这很好,但对于 可变的 类型(列表、字典、任何可以就地更改的内容)这会导致问题。最终发生的是 Thing 共享 content

    这样,就创建了空列表 每个 每次调用构造函数时,都会创建一个新列表。