2010-02-10 38 views
8

在python中可以有上面的代碼而不會引發異常?是否可以聲明一個沒有參數的函數,然後將一些參數傳遞給該函數而不會引發異常?

def myfunc(): 
    pass 

# TypeError myfunc() takes no arguments (1 given) 
myfunc('param') 

通常在一些情況下,我啓動一個沒有參數的函數,然後檢索函數內的參數。

在實踐中,我不想在myfunc中聲明參數,然後將一些參數傳遞給它。我找到的唯一解決方案是myfunc(*arg)。還有其他方法嗎?

+9

爲什麼'MYFUNC(* ARG)'不夠好? – interjay 2010-02-10 23:45:56

+3

我猜yuri沒有(還)知道* arg – Dana 2010-02-10 23:50:09

+0

實現需要myfunc是一個傳遞給另一個函數的回調函數,它嘗試在傳遞參數的列表理解中調用它。所以我沒有控制回調實現,用戶不能有意地忽略'* args'(在代碼中我關心這個事件) – yuri 2010-02-10 23:51:37

回答

10
>>> def myFunc(*args, **kwargs): 
... # This function accepts arbitary arguments: 
... # Keywords arguments are available in the kwargs dict; 
... # Regular arguments are in the args tuple. 
... # (This behaviour is dictated by the stars, not by 
... # the name of the formal parameters.) 
... print args, kwargs 
... 
>>> myFunc() 
() {} 
>>> myFunc(2) 
(2,) {} 
>>> myFunc(2,5) 
(2, 5) {} 
>>> myFunc(b = 3) 
() {'b': 3} 
>>> import dis 
>>> dis.dis(myFunc) 
    1   0 LOAD_FAST    0 (args) 
       3 PRINT_ITEM 
       4 LOAD_FAST    1 (kwargs) 
       7 PRINT_ITEM 
       8 PRINT_NEWLINE 
       9 LOAD_CONST    0 (None) 
      12 RETURN_VALUE 

而實際上回答的問題:不,我不認爲還有其他辦法。

主要原因很簡單: C python是基於堆棧的。一個不需要參數的函數將不會在堆棧上爲它分配空間(myFunc,而是將它們放在位置0和1中)。(查看評論)

另外一點是,您將如何訪問其他參數?

+2

堆棧評論是重點。 Python是基於堆棧的,但是參數傳遞(和解析)不是(參數始終是堆棧中的單個項目,即使沒有參數也是如此)。Python不會忽略參數的原因是因爲它會隱藏錯誤**。 – 2010-02-11 00:04:14

+0

這確實很有可能我誤讀了dis告訴我:) – badp 2010-02-11 00:13:29

4

當然可以!

您可以定義可變長度參數列表,像這樣:

def foo(*args): 
    print len(args) 

參數表是你的參數的元組因此調用:

foo(1,2) 

給你的元組(1,2)你的函數中。

+0

'args'實際上是一個元組。 – 2010-02-10 23:50:14

+0

哦,是的!固定! – Dana 2010-02-10 23:51:45

11

有通過ARGS在

By位置

>>> def myfunc(*args): 
... print "args", args 
... 
>>> myfunc("param") 
args ('param',) 

通過關鍵字

>>> def myfunc(**kw): 
... print "kw", kw 
... 
>>> myfunc(param="param") 
kw {'param': 'param'} 

兩種方式你可以同時使用

組合
>>> def myfunc(*args, **kw): 
... print "args", args 
... print "kw", kw 
... 
>>> myfunc("param") 
args ('param',) 
kw {} 
>>> 
>>> myfunc(param="param") 
args() 
kw {'param': 'param'} 
>>> 
>>> myfunc("param", anotherparam="anotherparam") 
args ('param',) 
kw {'anotherparam': 'anotherparam'} 
1

這裏是一個函數裝飾我寫來做到這一點,與使用情況的一個例子沿:

def IgnoreExtraArguments(f): 
    import types 
    c = f.func_code 
    if c.co_flags & 0x04 or c.co_flags&0x08: 
     raise ValueError('function already accepts optional arguments') 
    newc = types.CodeType(c.co_argcount, 
        c.co_nlocals, 
        c.co_stacksize, 
        c.co_flags | 0x04 | 0x08, 
        c.co_code, 
        c.co_consts, 
        c.co_names, 
        c.co_varnames+('_ignore_args','_ignore_kwargs'), 
        c.co_filename, 
        c.co_name, 
        c.co_firstlineno, 
        c.co_lnotab, 
        c.co_freevars, 
        c.co_cellvars) 
    f.func_code = newc 
    return f 

if __name__ == "__main__": 
    def f(x,y): 
     print x+y 

    g = IgnoreExtraArguments(f) 
    g(2,4) 
    g(2,5,'banana') 

    class C(object): 
     @IgnoreExtraArguments 
     def m(self,x,y): 
      print x-y 

    a=C() 
    a.m(3,5) 
    a.m(3,6,'apple') 
相關問題