user1501873
user1501873

Reputation: 1

Implementation of a function

I have a problem with the implementation of a function.

The aim is to decrease the value of a key in the dictionary hand if it is in the word. For example:

word = hi
hand = {'h':2,'i':1}

-> function update_hand(word,hand)

hand = {'h'1}

so I tried:

def update_hand(hand, word):
    for letter in range(len(word)):
        if hand.get(word[letter],0) != 0:
            hand[word[letter]] -= 1
            if hand.get(word[letter],0) == 0:
                del hand[word[letter]]
    return hand

but when I call it, I get:

Traceback (most recent call last):
File "/home/phillip/Desktop/ps3/ps3/ps3a.py", line 168, in <module>
print update_hand('quali', {'a': 1, 'i': 1, 'm': 1, 'l': 2, 'q': 1, 'u': 1})
File "/home/phillip/Desktop/ps3/ps3/ps3a.py", line 162, in update_hand
if hand.get(word[letter],0) != 0:
AttributeError: 'str' object has no attribute 'get'

So I tried to implement it in a test file (just the for loot) and everything works fine... well, I have no idea what I did wrong.

Thanks, Phillip

Upvotes: 0

Views: 164

Answers (2)

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

And to really answer the question: you defined your function as def update_hand(hand, word) but you obviously call it as update_hand(word, hand). Both dict and str are iterable and sizeable, but str don't have a get method.

A quick and simple way to debug such problem: add print statements in your code, ie :

def update_hand(hand, word):
    print "update_hand(%s, %s)" % (hand, word)
    # code here

and don't forget to remove the print statement once you've fixed the problem.

Also as Antimony mentioned you don't need the ugly indexing. Jakob posted a neat version using collections.Counter but if you're stuck with an older (< 2.7.x) Python version here's a more canonical implementation:

def update_hand(hand, word):
    for letter in word:
        count = hand.get(letter, 0)
        if count > 1:
            # avoids a KeyError if letter was not in hand 
            # XXX spec : should this happen ?
            hand[letter] = count - 1
        else:
            # count is already <= 1 so decreasing it would make it <= 0
            del hand[letter]

    return hand

Upvotes: 1

Jakob Bowyer
Jakob Bowyer

Reputation: 34708

from collections import Counter

hand = Counter()

def update_hand(word, hand):
    for token in word:
        if hand[token] == 0:
           del hand[token]
        else: 
           hand[token] -= 1

Using collections.Counter makes this task trivial

Upvotes: 1

Related Questions