Reputation: 13
Doing a self-study of Python via MIT Open Courseware, and ran into a problem with this bit of code below. When I run this function either alone or within another function, it mutates the originally passed value 'hand', and I am not sure why. I set two local variables (hand0 and tester) to hand, the first to preserve the initial value, and the second to iterate over. However, all three change, while I'm only expecting 'tester' to do so. Other than mutating 'hand', the function works as expected.
(Values as passed to the function vary within set parameters: word_list is a list of valid English words, word is a string that I replace within this function for testing, and hand is a dictionary of letters and their associated counts. Debugging code commented out.)
def is_valid_word(word, hand, word_list):
"""
Returns True if word is in the word_list and is entirely
composed of letters in the hand. Otherwise, returns False.
Does not mutate hand or word_list.
word: string
hand: dictionary (string -> int)
word_list: list of lowercase strings
"""
hand0 = hand
tester = hand
#display_hand(hand)
#display_hand(tester)
word = raw_input('test word: ')
length = len(word)
disc = True
for c in range(length):
if word[c] in tester.keys() and tester[word[c]]>0:
#print tester[word[c]]
#display_hand(hand)
#display_hand(tester)
tester[word[c]]=tester[word[c]]-1
else:
#print 'nope'
disc = False
if word not in word_list:
disc = False
#print disc
#display_hand(hand)
#display_hand(tester)
#display_hand(hand0)
return disc
Upvotes: 1
Views: 1438
Reputation: 308168
When you do tester = hand
you're not making a copy of hand
, you're making a new reference to the same object. Any modifications you make to tester
will be reflected in hand
.
Use tester = hand.copy()
to fix this: http://docs.python.org/2/library/stdtypes.html#dict.copy
Upvotes: 5
Reputation: 309919
When you do tester = hand
, you're only creating a new reference to the hand
object. In other words, tester
and hand
are the same object. You could see this if you checked their id
:
print id(tester)
print id(hand) #should be the same as `id(tester)`
Or equivalently, compare with the is
operator:
print tester is hand #should return `True`
To make a copy of a dictionary, there is a .copy
method available:
tester = hand.copy()
Upvotes: 10