"""This module contains a code example related to12Think Python, 2nd Edition3by Allen Downey4http://thinkpython2.com56Copyright 2015 Allen Downey78License: http://creativecommons.org/licenses/by/4.0/9"""1011from __future__ import print_function, division1213"""1415WARNING: this program contains a NASTY bug. I put16it there on purpose as a debugging exercise, but17you DO NOT want to emulate this example!1819"""2021class Kangaroo:22"""A Kangaroo is a marsupial."""2324def __init__(self, name, contents=[]):25"""Initialize the pouch contents.2627name: string28contents: initial pouch contents.29"""30# The problem is the default value for contents.31# Default values get evaluated ONCE, when the function32# is defined; they don't get evaluated again when the33# function is called.3435# In this case that means that when __init__ is defined,36# [] gets evaluated and contents gets a reference to37# an empty list.3839# After that, every Kangaroo that gets the default40# value gets a reference to THE SAME list. If any41# Kangaroo modifies this shared list, they all see42# the change.4344# The next version of __init__ shows an idiomatic way45# to avoid this problem.46self.name = name47self.pouch_contents = contents4849def __init__(self, name, contents=None):50"""Initialize the pouch contents.5152name: string53contents: initial pouch contents.54"""55# In this version, the default value is None. When56# __init__ runs, it checks the value of contents and,57# if necessary, creates a new empty list. That way,58# every Kangaroo that gets the default value gets a59# reference to a different list.6061# As a general rule, you should avoid using a mutable62# object as a default value, unless you really know63# what you are doing.64self.name = name65if contents == None:66contents = []67self.pouch_contents = contents6869def __str__(self):70"""Return a string representaion of this Kangaroo.71"""72t = [ self.name + ' has pouch contents:' ]73for obj in self.pouch_contents:74s = ' ' + object.__str__(obj)75t.append(s)76return '\n'.join(t)7778def put_in_pouch(self, item):79"""Adds a new item to the pouch contents.8081item: object to be added82"""83self.pouch_contents.append(item)848586kanga = Kangaroo('Kanga')87roo = Kangaroo('Roo')88kanga.put_in_pouch('wallet')89kanga.put_in_pouch('car keys')90kanga.put_in_pouch(roo)9192print(kanga)93print(roo)9495# If you run this program as is, it seems to work.96# To see the problem, trying printing roo.979899