0

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

1
  • There's no need to do that awkward for letter in range(len(word)): , word[letter] stuff. Just iterate over the string directly. Commented Jul 4, 2012 at 15:01

2 Answers 2

1
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

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.