Python: How do you return multiple variables from a function

Started by
4 comments, last by Splinter of Chaos 17 years, 9 months ago
I'm trying to creat a parser because after about two weeks of programming, surprisingly it seems I'm ready. But I've encountered two problems, the first has been solved independantly, but the second revolves around my use of the return statement and the nessesity of returning more that one item. I made two different versions, both have the same problem. Here's the first and original:
def get_input(): # Tested. Works.
    """Demands input.

    Asks for input and makes sure there was infact input."""
    global act
    while len(act) == 0:
        act = raw_input("What would you like to do?\n")
        if len(act) < 0:
            print "No command has been given. Please try again."
            return
        else:
            actOld = act
            act = act.lower()
            actList = act.rsplit()
            
    # [02 BUG] Only the first variable is returned.
    # <2006-07-07>
    return act ,actOld ,actList
The "[02 BUG]" is just how I document my bugs errors and stuff, (before the code actually starts I have an index of bugs, things needing doing, etc etc. And the problem is proclaimed in the code. Here's the second.
def get_input():
    """Demands input.

    Asks for input and makes sure there was infact input."""
    global act
    while len(act) == 0:
        act = raw_input("What would you like to do?\n")
        if len(act) < 0:
            print "No command has been given. Please try again."
            return
        else:
            actOld = act
            act = act.lower()
            actList = act.rsplit()
            
            # The return statement only workd for one var so a list was made.
            # act = 0; actOld = 1; actList = 2
            goal = [act, actOld, actList]
            
    # [02 BUG] The list is not returned AT ALL!
    # <2006-07-07>
    return goal
I thought that by putting in a list instead of a normal variable it would carry through, but it made it worse, as I said in the code, the list wasn't returned at all!
Advertisement
How are you calling those functions? Both forms of return are fine. My guess is that perhaps something else is going wrong.
This works just fine:
def foo():    return 1, 2, 3x, y, z = foo()

Both versions of your get_input() function look like they have a couple of bugs. First, the str object does not have an rsplit() method, so an AttributeError exception will be raised at this point in the code.

Secondly, where is 'act' cleared? If it's not being cleared outside of this function and guaranteed to be cleared between calls, the while loop will cause control to flow directly to the return. Since you're trying to save the old value of act when you get new input, it looks like you're assuming act is not cleared. You need to review this logic and make it consistent.
Quote:Original post by kinetik_mjg

Both versions of your get_input() function look like they have a couple of bugs. First, the str object does not have an rsplit() method, so an AttributeError exception will be raised at this point in the code.


??? Do you mean the act that I want lowercase should be this?
[soource lang="python"] act = act.rsplit().lower()[/source]
If not, be be more specific or more lamen, but my guess is on more specific.

And as for "where is act cleared?"
I your asking where I delet the variable for later use so it doesn't mess up my code. In that case, I clear it when I'm done using it. I wouldn't clear it until I've processed the input and responded would I? But again, if I'm not understanding your question, be more specific or more lamens.

(Note: I don't ask that you be more lamens (that is if I don't understand you, otherwise it's good,) because I don't want to learn the terms, but because I still have to learn them.

EDIT:
Quote:Original post by Kylotan
How are you calling those functions? Both forms of return are fine. My guess is that perhaps something else is going wrong.


Hm. Well, the main block looks like this.
for x in range(1,2):    get_input()    print goal    if act:        process_input(act)


Although I've changed it thanks to kinetik_mjg's advice to this:
for x in range(1,2):    act ,actOld ,actList = get_input()    # Test print, WORKS    print act, actList, actOld    if act:        process_input(act)



[Edited by - Splinter of Chaos on July 8, 2006 4:32:57 PM]
Oops, ignore my remark about rsplit()--I see that it's new in Python 2.4.

As for clearing act, I'll demonstrate with code:
act = ""def get_input():    global act    # this test will be false if act has not been cleared and the code    # will try to return actOld and actList, which are only set in the else    while len(act) == 0:        act = raw_input("What would you like to do?\n")                # this test will never be true, so code always goes into else part        if len(act) < 0:            print "No command has been given. Please try again."            return        else:            actOld = act            act = act.lower()            actList = act.rsplit()    return act, actOld, actList# works first timex, y, z = get_input()print "act='%s', x='%s', y='%s', z='%s'" % (act, x, y, z)# but not this time (UnboundLocalError: local variable 'actOld' referenced before assignment)x, y, z = get_input()print "act='%s', x='%s', y='%s', z='%s'" % (act, x, y, z)# so we need to clear act first, and then it worksact = ""x, y, z = get_input()print "act='%s', x='%s', y='%s', z='%s'" % (act, x, y, z)

I assume that in your case, your process_input() function is responsible for clearing act?

So, returning multiple values works as expected, but the code is broken if act has not been cleared before it is called again. This should be fixed up. The len(act) < 0 test is also broken and needs to be fixed (maybe len(act) == 0?). I would strongly recommend changing the code so that it does not rely on act being global--use of global variables makes code very fragile.
Okay . . . but then how do I use act then? I have about three (thus far) different functions that all require the use of act, do you sugest I call get_input() for each one?

And lastly, what is the rsplit()? I do have Python 2.4, do I use it or don't?

EDIT:
The Python documentation said
Quote:rsplit( [sep [,maxsplit]])
Return a list of the words in the string, using sep as the delimiter string. If maxsplit is given, at most maxsplit splits are done, the rightmost ones. If sep is not specified or None, any whitespace string is a separator. Except for splitting from the right, rsplit() behaves like split() which is described in detail below. New in version 2.4.


Sounds like I don't really need this because I can keep the string a string and still parse fine. I see no disadvantages, but also no advantages for using rsplit().

This topic is closed to new replies.

Advertisement