在python中的一行中分配函数调用的结果

Assign results of function call in one line in python

当结果在python中按名称(不可索引)存储时,如何将函数调用的结果分配给多个变量。

例如(在python 3中测试)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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()

我们不想做的事

如果结果是可索引的(Cat扩展元组/列表,我们使用了一个namedtuple等),我们可以简单地按照Cat类上面的注释编写A,B = foo()。例如,这就是这里推荐的。

假设我们有充分的理由不允许这样做。也许我们喜欢从变量名(如果变量名比xy更有意义)进行赋值,或者对象主要不是容器。可能字段是属性,所以访问实际上涉及一个方法调用。不过,我们不需要假设任何一个问题来回答这个问题;Cat类可以按面值计算。

这个问题已经讨论了如何以可能的最佳方式设计函数/类;如果函数的预期返回值已经定义好,并且不涉及类似元组的访问,那么返回时接受多个值的最佳方式是什么?


我强烈建议使用多个语句,或者只保留结果对象而不解包其属性。也就是说,您可以使用operator.attrgetter来实现这一点:

1
2
from operator import attrgetter
a, b, c = attrgetter('a', 'b', 'c')(foo())