"""
This program is part of an exercise in
Think Python: An Introduction to Software Design
Allen B. Downey
This program explains and corrects a bug in BadKangaroo.py.
Before reading this, you should try to debug BadKangaroo.
"""
class Kangaroo(object):
"""a Kangaroo is a marsupial"""
def __init__(self, contents=[]):
# The problem is the default value for contents.
# Default values get evaluated ONCE, when the function
# is defined; they don't get evaluated again when the
# function is called.
# In this case that means that when __init__ is defined,
# [] gets evaluated and contents gets a reference to
# an empty list.
# After that, every Kangaroo that gets the default
# value get a reference to THE SAME list. If any
# Kangaroo modifies this shared list, they all see
# the change.
# The next version of __init__ shows an idiomatic way
# to avoid this problem.
self.pouch_contents = contents
def __init__(self, contents=None):
# In this version, the default value is None. When
# __init__ runs, it checks the value of contents and,
# if necessary, creates a new empty list. That way,
# every Kangaroo that gets the default value get a
# reference to a different list.
# As a general rule, you should avoid using a mutable
# object as a default value, unless you really know
# what you are doing.
if contents == None:
contents = []
self.pouch_contents = contents
def __str__(self):
"""return a string representation of this Kangaroo and
the contents of the pouch, with one item per line"""
t = [ object.__str__(self) + ' with pouch contents:' ]
for obj in self.pouch_contents:
s = ' ' + object.__str__(obj)
t.append(s)
return '\n'.join(t)
def put_in_pouch(self, item):
"""add a new item to the pouch contents"""
self.pouch_contents.append(item)
kanga = Kangaroo()
roo = Kangaroo()
kanga.put_in_pouch('wallet')
kanga.put_in_pouch('car keys')
kanga.put_in_pouch(roo)
print kanga
print ''
print roo