I learned Python last year, and was just getting back into it with a new project. I’ve hit a snag right at the beginning, and after a bunch of poring through documentation I’m still stumped. I have to believe it’s something simple, but I can’t find it. Here’s the issue:
I have the following set up in a file:
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
Then from an interactive prompt I do:
>>> import things
>>> a = things.Wrapper("This is a title")
Now, I would expect at this point that the body attribute of a would be a Thing instance with the name "BODY" and a content consisting of an empty list. What I’m surprised to find is that its content is actually a list containing the same "TITLE" instance that a.header.content holds.
>>> 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']
I can’t for the life of me figure out how a.body.content got assigned that way. Can anyone shed some light on this?
Try this
The issue with [] as a default is that the default parameters are only evaluated once, when the interpreter first creates the function. For an
intor other immutable type this is fine, but for mutable types (lists, dictionaries, anything that can be changed in place) this causes problems. What winds up happening is that all instances ofThingshare the samecontent.This way, the empty list is created each time you call the constructor, creating a new list every time.