stephan
stephan

Reputation: 2403

How to return multiple variables from a Python function

I am new to Python and trying to experiment by creating an address book. I suspect I have a problem with the displayPerson function. Can I not return multiple variables at the same time?

def lowercasewrapper(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs).lower()
    return wrapper

#Class with object attributes
class People():
    numofpeeps = 0
    listofpeeps = []
    def __init__(self, name, age, phone, fblink):
        self.name=name
        self.age=age
        self.phone=phone
        self.fblink=fblink
        People.numofpeeps += 1
        People.listofpeeps.append(self.age)

    @lowercasewrapper #calling the wrapper, to make all strings lowercase
    def displayPerson(self): 
        return self.name, self.age, self.phone, self.fblink

george=People("gEORge", "5", "503-405-4021", "http://facebook.com/boobs")
dave=People("dave", "10", "971-863-3905", "http://boobs.com")
charlie=People("CHARLIE", "19", "823-405-2942", "http://boobs.com")

print george.displayPerson()
print "Total number of people: ", People.numofpeeps
print "List of ages: ", People.listofpeeps


error shows the following: File "example.py", line 54, in <module>
    print george.displayPerson()
  File "example.py", line 31, in wrapper
    return func(*args, **kwargs).lower()
AttributeError: 'tuple' object has no attribute 'lower'

Upvotes: 3

Views: 2310

Answers (4)

Mac
Mac

Reputation: 14791

Sure, you can return multiple values from a function. That's not your problem.

When you return multiple values from a function, Python automatically wraps them up in a tuple. So when you call displayPerson, it returns a tuple containing the person's name, age, phone number and facebook link in that order.

Now, in your lowercase wrapper you take the result from calling displayPerson, and call the lower method on it. Unfortunately, tuples don't have a lower method.

Instead, you'll need to return a new tuple with each of the elements individually converted to lower case:

def lowercasewrapper(func):
    def wrapper(*args, **kwargs):
        # Get initial result of your function.
        initial_tuple = func(*args, **kwargs)
        # Create a new tuple consisting of each member of the
        # initial tuple, converted to lower case.
        new_tuple = tuple([x.lower() for x in initial_tuple])
        return new_tuple
    return wrapper

Note: this could be done in a single line, I used a couple here to illustrate what's going on.

Upvotes: 0

Donald Miner
Donald Miner

Reputation: 39933

In this line:

    return func(*args, **kwargs).lower()

You are taking the return of that and calling it lower. When you do:

    return self.name, self.age, self.phone, self.fblink

What that really does is packs those 4 variables into a tuple, and then returns that.

So, unfortunately you are trying to call .lower() on a tuple, not on each item. Instead, you want to go through and call .lower() on everything inside:

def lowercasewrapper(func):
    def wrapper(*args, **kwargs):

        return tuple(item.lower() for item in func(*args, **kwargs))
    return wrapper

This uses a list comrpehension. If you haven't seen that syntax yet, you might want to use a for-loop to iterate over each item and lower case it.

Upvotes: 1

zero323
zero323

Reputation: 330393

Exception is raised by the lowercasewrapper not the displayPerson. You can use this instead:

def lowercasewrapper(func):
    def wrapper(*args, **kwargs):
        return [x.lower() for x in func(*args, **kwargs)]
    return wrapper

Read @DonaldMiner answer for a better explanation.

Upvotes: 1

Alex Suo
Alex Suo

Reputation: 3129

Just

def myFunc():
    return 1, 2

and in caller

var1, var2 = yourFunc()

Upvotes: 1

Related Questions