forked from AllenDowney/ThinkPython2
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathGoodKangaroo.py
97 lines (74 loc) · 2.71 KB
/
GoodKangaroo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""This module contains a code example related to
Think Python, 2nd Edition
by Allen Downey
http://thinkpython2.com
Copyright 2015 Allen Downey
License: http://creativecommons.org/licenses/by/4.0/
"""
from __future__ import print_function, division
"""
WARNING: this program contains a NASTY bug. I put
it there on purpose as a debugging exercise, but
you DO NOT want to emulate this example!
"""
class Kangaroo:
"""A Kangaroo is a marsupial."""
def __init__(self, name, contents=[]):
"""Initialize the pouch contents.
name: string
contents: initial pouch 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 gets 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.name = name
self.pouch_contents = contents
def __init__(self, name, contents=None):
"""Initialize the pouch contents.
name: string
contents: initial pouch contents.
"""
# 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 gets 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.
self.name = name
if contents == None:
contents = []
self.pouch_contents = contents
def __str__(self):
"""Return a string representaion of this Kangaroo.
"""
t = [ self.name + ' has 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):
"""Adds a new item to the pouch contents.
item: object to be added
"""
self.pouch_contents.append(item)
kanga = Kangaroo('Kanga')
roo = Kangaroo('Roo')
kanga.put_in_pouch('wallet')
kanga.put_in_pouch('car keys')
kanga.put_in_pouch(roo)
print(kanga)
print(roo)
# If you run this program as is, it seems to work.
# To see the problem, trying printing roo.