*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']

你如何有效地使用它们?

169907 次浏览

*args和/或**kwargs作为函数定义参数列表的最后一项,允许该函数接受任意数量的参数和/或关键字参数。

例如,如果你想写一个函数,返回所有参数的和,不管你提供了多少个参数,你可以这样写:

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

它可能在面向对象编程中更常用,当你重写一个函数,并想用用户传入的参数调用原始函数时。

你实际上不必称它们为argskwargs,这只是一种惯例。它是***起作用的。

Python官方文档有更深入的观察

此外,我们还使用它们来管理继承。

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就不会真正知道(或关心)超类初始化是什么。如果您意识到需要更改父类,则可以修复这些问题,而不必在每个子类中处理细节。

注意S.Lott的评论中很酷的事情——你也可以调用带有*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

*args**kwargs的另一个好用途是:可以定义通用的“catch all”函数,这对于返回这样一个包装器而不是原始函数的装饰器非常有用。

一个简单的缓存装饰器的例子:

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

只是为了阐明如何解包参数,以及处理缺失的参数等等。

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