2008-11-13 136 views
231

*args**kwargs是什麼意思?* args和** kwargs是什麼意思?

根據Python文檔,從它看起來,它傳遞了一個參數元組。

def foo(hello, *args): 
    print hello 

    for each in args: 
     print each 

if __name__ == '__main__': 
    foo("LOVE", ["lol", "lololol"]) 

此打印出:

LOVE 
['lol', 'lololol'] 

你如何有效地使用它們?

+13

只是一個關於小時和公斤 - 瓦特小時。 – Mostlyharmless 2008-11-13 15:47:09

+6

這篇文章對深入理解主題非常有用:http://agiliq.com/blog/2012/06/understanding-args-and-kwargs/ – 2012-12-29 08:04:42

回答

225

*args和/或**kwargs作爲函數定義的參數列表中的最後一項允許該函數接受任意數量的參數和/或關鍵字參數。

例如,如果你想寫一個返回的所有參數,和的功能,無論你提供多少,你可以寫這樣的:

def my_sum(*args): 
    return sum(args) 

它可能更常用面向對象編程,當你重寫的功能,並要撥打與任何參數的用戶通過在原有的功能。

你實際上並沒有給他們打電話argskwargs,這只是一個慣例。這是神奇的***

官方的Python文檔有a more in-depth look

+5

沒有汗水,非常受歡迎。以及困惑我一段時間。 如果您認真學習Python,我會衷心推薦Mark Lutz編寫的'Programming Python'。 – 2008-11-13 14:48:10

+39

也許鏈接到深入解釋這個問題的教程,並且應該被所有人閱讀:http://docs.python.org/tutorial/controlflow.html#more-on-defining-functions – 2008-11-13 15:02:04

82

另外,我們使用它們來管理繼承。

class Super(object): 
    def __init__(self, this, that): 
     self.this = this 
     self.that = that 

class Sub(Super): 
    def __init__(self, myStuff, *args, **kw): 
     super(Sub, self).__init__(*args, **kw) 
     self.myStuff= myStuff 

x= Super(2.7, 3.1) 
y= Sub("green", 7, 6) 

這樣Sub並不真正知道(或關心)超類的初始化是什麼。如果你意識到你需要改變超類,那麼你可以修正一些東西,而不必爲每個子類中的細節出汗。

63

注意在S.Lott's comment很酷的事情 - 你也可以調用函數與*mylist**mydict解壓位置和關鍵字參數:

def foo(a, b, c, d): 
    print a, b, c, d 

l = [0, 1] 
d = {"d":3, "c":2} 

foo(*l, **d) 

會打印:0 1 2 3

24

另一個很好的使用了*args**kwargs:你可以定義泛型的「全部捕獲」函數,這對裝飾器來說非常適用,你可以返回這種包裝器而不是原始函數。

用一個簡單的緩存裝飾一個例子:

import pickle, functools 
def cache(f): 
    _cache = {} 
    def wrapper(*args, **kwargs): 
    key = pickle.dumps((args, kwargs)) 
    if key not in _cache: 
     _cache[key] = f(*args, **kwargs) # call the wrapped function, save in cache 
    return _cache[key] # read value from cache 
    functools.update_wrapper(wrapper, f) # update wrapper's metadata 
    return wrapper 

import time 
@cache 
def foo(n): 
    time.sleep(2) 
    return n*2 

foo(10) # first call with parameter 10, sleeps 
foo(10) # returns immediately 
15

只是爲了澄清如何解壓的參數,並利用缺少參數等保健

def func(**keyword_args): 
    #-->keyword_args is a dictionary 
    print 'func:' 
    print keyword_args 
    if keyword_args.has_key('b'): print keyword_args['b'] 
    if keyword_args.has_key('c'): print keyword_args['c'] 

def func2(*positional_args): 
    #-->positional_args is a tuple 
    print 'func2:' 
    print positional_args 
    if len(positional_args) > 1: 
    print positional_args[1] 

def func3(*positional_args, **keyword_args): 
    #It is an error to switch the order ie. def func3(**keyword_args, *positional_args): 
    print 'func3:' 
    print positional_args 
    print keyword_args 

func(a='apple',b='banana') 
func(c='candle') 
func2('apple','banana')#It is an error to do func2(a='apple',b='banana') 
func3('apple','banana',a='apple',b='banana') 
func3('apple',b='banana')#It is an error to do func3(b='banana','apple')