craigread7
craigread7

Reputation: 13

python "need more than 1 value to unpack"

Trying to run a script from "Learn Python the hard way" and getting this error, tried several things but I'm kinda stuck. Seen similar errors with people using argv and not enough arguments when running the script

Error points to Line 70:

question, answer = convert(snippet, phrase)

full code:

import random
from urllib import urlopen
import sys

WORD_URL = "http://learncodethehardway.org/words.txt"
WORDS = []

PHRASES = {
        "class %%%(%%%):":
            "Make a class named %%% that is-a %%%",
        "class %%%(object):\n\tdef __init__(self, ***)" :
            "class %%% has-a __init__ that takes self and *** parameters.",
        "class %%%(object):\n\tdef ***(self, @@@)" :
            "class %%% has-a function named *** that takes self and @@@ parameters.",
        "*** = %%%()":
            "Set *** to an instance of class %%%",
        "***.***(@@@)":
            "From *** get the *** function, nd call it with parameters self, @@@",
        "***.*** = '***'":
            "From *** get the *** attribute and set it to '***'."
            }
#do they want to drill phrases first

PHRASE_FIRST = False
if len(sys.argv) == 2 and sys.argv[1] == "English":
    PHRASE_FIRST = True

#load up the words from the website
for word in urlopen(WORD_URL).readlines():
    WORDS.append(word.strip())


def convert(snippet, phrase):
    class_names = [w.capitalize() for w in
    random.sample(WORDS, snippet.count("%%%"))]
    other_names = random.sample(WORDS, snippet.count("***"))
    results = []
    param_names = []

    for i in range(0, snippet.count("@@@")):
        param_count = random.randint(1, 3)
        param_names.append(", ".join(random.sample(WORDS, param_count)))

    for sentence in snippet, phrase:
        result = sentence[:]

#fake class names
    for word in class_names:
        result = result.replace("%%%", word, 1)

    #fake other names

    for word in other_names:
        result = result.replace("***", word, 1)

    for word in param_names:
        result = result.replace("@@@", word, 1)

    results.append(result)
    return results

#keep going until they hit CTRL-D
try:
        while True:
            snippets = PHRASES.keys()
            random.shuffle(snippets)

            for snippet in snippets:
                phrase = PHRASES[snippet]
                question, answer = convert(snippet, phrase)
                if PHRASE_FIRST:
                    question, answer = answer, question
                print question

            raw_input("> ")
            print "ANSWER: %s\n\n" % answer
except EOFError:
    print "\nBye"

Upvotes: 0

Views: 1112

Answers (3)

ehindy
ehindy

Reputation: 459

The above comments are correct for the issue you are experiencing however the code example posted is not showing correct indentation. The for sentence in snippet, phrase loop in the class is not appending the extra value that will then result in a correct question, answer = convert(snippet, phrase). Change the code to the below and it should run fine(tested it here):

for sentence in snippet, phrase:
    result = sentence[:]

    #fake class names
    for word in class_names:
        result = result.replace("%%%", word, 1)

    #fake other names
    for word in other_names:
        result = result.replace("***", word, 1)

    for word in param_names:
        result = result.replace("@@@", word, 1)

    results.append(result)
return results

Upvotes: 2

MattCorr
MattCorr

Reputation: 371

Problem

In your code, convert() returns a list, which is one object, or value. By doing question, answer = convert(snippet, phrase), you are expecting two values to be returned, and then inserted into question and answer.

Solution

You should a change

question, answer = convert(snippet, phrase)

to

results = convert(snippet, phrase)

You can then get question and answer from results(assuming they are at indices 0 and 1) by doing

question = results[0]
answer = results[1]

Upvotes: -1

Pythonista
Pythonista

Reputation: 11635

You're trying to unpack two values from results which is returned by your function convert(*args).

However, in your function convert you are returning a list with a single item result which is appended to results. So, you only have one value not two to unpack

For the sake of completeness....

Let's say your function convert returned more than two values in this list and you tried to unpack them. You'd also get an error, but this time you'd have too many values to unpack. In this case you do something along the lines of this:

some_var, *other = convert(snippet, phrase)

Upvotes: 1

Related Questions