1

python中有没有办法从被调用的函数内部检查调用函数的输出参数的数量?

例如:

a,b = Fun() #-> number of output arguments would be 2
a,b,c = Fun() #-> number of output arguments would be 3

在 matlab 中,这将使用nargout来完成, 我知道这样做的“正常方式”是将不需要的值解压缩到 _ 变量中:

def f():
    return 1, 2, 3

_, _, x = f()

我想要完成的事情很简单。我有一个函数,如果用一些参数或两个对象调用,它将返回一个对象:

def f(a,b=None):
    if b is None:
        return 1
    else:
        return 1,2

但我想强制元组解包不发生并强制出错,例如:

x = f(a) #-> Fine
x,y = f(a,b) #-> Fine
x,y = f(a) #-> Will throw native error: ValueError: need more than Foo values to unpack
x = f(a,b) #-> Want to force this to throw an error and not default to the situation where x will be a tuple.
4

2 回答 2

2

正如 Ashwini 指出的那样,这似乎可行:

import inspect,dis

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

def cleverfunc():
    howmany = expecting()
    if howmany == 0:
        print("return value discarded")
    if howmany == 2:
        return 1,2
    elif howmany == 3:
        return 1,2,3
    return 1

def test():
    cleverfunc()
    x = cleverfunc()
    print(x)
    x,y = cleverfunc()
    print(x,y)
    x,y,z = cleverfunc()
    print(x,y,z)

test()
于 2013-05-10T20:09:42.737 回答
1

如果您使用 Python 3,则可以在 LH 上使用扩展的可迭代解包:

>>> def f(n):
...    return tuple(range(n))
... 
>>> f(3)
(0, 1, 2)
>>> a,b,*c=f(20)
>>> a
0
>>> b
1
>>> c
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

使用您的功能,您可以执行以下操作:

>>> def f(a,b=None):
...     if b is None:
...         return 1
...     else:
...         return 1,2
>>> rtr,*_=f(1),None
>>> rtr
1
>>> rtr,*_=f(1,True),None
>>> rtr
(1, 2)

在任何一种情况下,_将是None并且rtr将是1(1,2)

您可能希望从 f 显式返回一个元组以避免以后的歧义:

>>> def f(a,b=None):
...    return (1,2) if b else (1,)
... 
>>> rtr,*_=f(1),None
>>> rtr
(1,)
>>> rtr,*_=f(1,True),None
>>> rtr
(1,2)

如果你这样做——它也可以在 Python 2X 下工作:

蟒蛇 2.7:

>>> def f(a,b=None):
...    return (1,2) if b else (1,)
... 
>>> x,y=f(1),None
>>> x
(1,)
>>> x,y=f(1,True),None
>>> z
>>> x
(1, 2)
于 2013-05-10T20:29:22.277 回答