1

How can I assign the results of a function call to multiple variables when the results are stored by name (not index-able), in python.

For example (tested in Python 3),

import random

# foo, as defined somewhere else where we can't or don't want to change it
def foo():
    t = random.randint(1,100)
    # put in a dummy class instead of just "return t,t+1" 
    # because otherwise we could subscript or just A,B = foo()
    class Cat(object):
        x = t
        y = t + 1

    return Cat()

# METHOD 1
# clearly wrong; A should be 1 more than B; they point to fields of different objects
A,B = foo().x, foo().y
print(A,B)

# METHOD 2
# correct, but requires two lines and an implicit variable
t = foo()
A,B = t.x, t.y
del t # don't really want t lying around
print(A,B)

# METHOD 3
# correct and one line, but an obfuscated mess
A,B = [ (t.x,t.y) for t in (foo(),) ][0]
print(A,B) 
print(t) # this will raise an exception, but unless you know your python cold it might not be obvious before running

# METHOD 4
# Conforms to the suggestions in the links below without modifying the initial function foo or class Cat.
# But while all subsequent calls are pretty, but we have to use an otherwise meaningless shell function
def get_foo():
    t = foo()
    return t.x, t.y

A,B = get_foo()

What we don't want to do

If the results were indexable ( Cat extended tuple/list, we had used a namedtuple, etc.), we could simply write A,B = foo() as indicated in the comment above the Cat class. That's what's recommended here , for example.

Let's assume we have a good reason not to allow that. Maybe we like the clarity of assigning from the variable names (if they're more meaningful than x and y) or maybe the object is not primarily a container. Maybe the fields are properties, so access actually involves a method call. We don't have to assume any of those to answer this question though; the Cat class can be taken at face value.

This question already deals with how to design functions/classes the best way possible; if the function's expected return value are already well defined and does not involve tuple-like access, what is the best way to accept multiple values when returning?

1 Answer 1

3

I would strongly recommend either using multiple statements, or just keeping the result object without unpacking its attributes. That said, you can use operator.attrgetter for this:

from operator import attrgetter
a, b, c = attrgetter('a', 'b', 'c')(foo())
Sign up to request clarification or add additional context in comments.

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.