Python检查函数调用时的输出参数数量
python中有没有一种方法可以从被调用函数的内部检查调用函数的输出参数的数量 例如:Python检查函数调用时的输出参数数量,python,matlab,arguments,return,Python,Matlab,Arguments,Return,python中有没有一种方法可以从被调用函数的内部检查调用函数的输出参数的数量 例如: a,b = Fun() #-> number of output arguments would be 2 a,b,c = Fun() #-> number of output arguments would be 3 x = f(a) #-> Fine x,y = f(a,b) #-> Fine x,y = f(a) #-> Will throw native error:
a,b = Fun() #-> number of output arguments would be 2
a,b,c = Fun() #-> number of output arguments would be 3
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.
在matlab中,这将使用
我知道这样做的目的是将不需要的值解包到u变量:
def f():
return 1, 2, 3
_, _, x = f()
我想做的很简单。我有一个函数,如果用一些参数调用,它将返回一个对象,否则将返回两个对象:
def f(a,b=None):
if b is None:
return 1
else:
return 1,2
但我想强制元组解包不发生,并强制出错,例如:
a,b = Fun() #-> number of output arguments would be 2
a,b,c = Fun() #-> number of output arguments would be 3
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.
正如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()
如果使用Python 3,可以在左侧使用:
>>> 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)
在任何一种情况下,\uuu
都将是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下工作:
Python 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)
你可能想浏览几个月前的档案。有人建议添加一个独立于迭代器协议的“解包协议”,这将使类似的事情变得微不足道。IIRC,这个想法被否决了,但是在这个过程中有人提出了一些“今天Python中的黑客实现”。注意,这取决于字节码,字节码只保证存在于参考实现CPython中,在其他Python实现中可能不起作用。即使在CPython中,操作码及其语义也可以在功能发布之间更改,而无需事先通知。特别是,Python 3.6中所有操作码的指令大小都发生了变化。此外,这不能正确处理扩展解包的情况(例如,使用
a、*b、c=func()
),在这种情况下,您可能希望返回尽可能多的结果(或文档,说明您的函数不是以这种方式调用的)。