2013-05-10 42 views
0

python有沒有一種方法來檢查函數被調用的函數內部調用的輸出參數的數量?Python的檢查一個函數被調用的輸出參數的數量

例如:

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

在MATLAB中,這將使用nargout 做我知道,這樣做的"normal way"是解壓不需要的值到_變量:

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. 
+0

您可能希望通過[蟒蛇思路(HTTP檔案脫脂:// mail.python.org/mailman/listinfo/python-ideas)。有人建議添加一個獨立於迭代器協議的「解包協議」,這會使這樣的事情幾乎微不足道。 IIRC,這個想法被擊落了,但是一路上有人提出了一些「今天Python中的黑客實現」。 – abarnert 2013-05-10 19:06:03

回答

1

由於阿什維尼指出,這似乎工作:

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() 
0

如果你使用Python 3,你可以在LH使用extended iterable unpacking

>>> 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) 

在這兩種情況下,_Nonertr要麼是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) 
相關問題