我有一个函数,当它被调用时,我想知道返回值将被分配给什么 - 特别是当它被解压缩为元组时。所以:
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)
答案 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