找出将解包返回值的值

时间:2013-05-10 11:24:44

标签: python

我有一个函数,当它被调用时,我想知道返回值将被分配给什么 - 特别是当它被解压缩为元组时。所以:

a = func()         # n = 1

VS

a, b, c = func()   # n = 3

我想在n中使用func的值。 inspect_getframe必须有一些魔法让我这样做。有什么想法吗?


免责声明(因为现在看来这似乎是必要的):我知道这是时髦的,不好的做法,不应该在生产代码中使用。它实际上看起来像我在Perl中期待的东西。我不是在寻找一种不同的方法来解决我所谓的“实际”问题,但我很好奇如何实现我上面提出的要求。这个技巧的一个很酷的用法是:

ONE, TWO, THREE = count()
ONE, TWO, THREE, FOUR = count()

def count():
    n = get_return_count()
    if not n:
        return
    return range(n)

2 个答案:

答案 0 :(得分:10)

改编自http://code.activestate.com/recipes/284742-finding-out-the-number-of-values-the-caller-is-exp/

import inspect
import dis

def expecting(offset=0):
    """Return how many values the caller is expecting"""
    f = inspect.currentframe().f_back.f_back
    i = f.f_lasti + offset
    bytecode = f.f_code.co_code
    instruction = ord(bytecode[i])
    if instruction == dis.opmap['UNPACK_SEQUENCE']:
        return ord(bytecode[i + 1])
    elif instruction == dis.opmap['POP_TOP']:
        return 0
    else:
        return 1

def count():
    # offset = 3 bytecodes from the call op to the unpack op
    return range(expecting(offset=3))

或者作为可以检测解包时的对象:

class count(object):
    def __iter__(self):
        # offset = 0 because we are at the unpack op
        return iter(range(expecting(offset=0)))

答案 1 :(得分:5)

关于Python如何做到这一点没有什么神奇之处。

简单地说,如果您在左侧使用多个目标名称,则右侧表达式必须返回匹配长度的序列

返回多个值的函数实际上只返回一个元组。这是一个标准的Python结构,一定长度的序列。您可以测量该长度:

retval = func()

print len(retval)

分配解包是在编译时确定的,你不能在左侧动态添加更多参数以适合你正在调用的函数。

Python 3允许您使用splat语法(通配符)来捕获解压缩的赋值的剩余部分:

a, b, *c = func()

c现在将是一个列表,其中包含超出前2的所有剩余值:

>>> def func(*a): return a
... 
>>> a, b, *c = func(1, 2)
>>> a, b, c
(1, 2, [])
>>> a, b, *c = func(1, 2, 3)
>>> a, b, c
(1, 2, [3])
>>> a, b, *c = func(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: need more than 1 value to unpack