*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']
如何有效地使用它们?
*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']
如何有效地使用它们?
将*args
和/或**kwargs
放在函数定义的参数列表末尾,允许该函数接受任意数量的参数和/或关键字参数。
例如,如果您想编写一个函数,返回其所有参数的总和,无论您提供多少个参数,您可以像这样编写它:
def my_sum(*args):
return sum(args)
在面向对象编程中,当你要覆盖一个函数并希望使用用户传递的任何参数调用原始函数时,*
和**
是非常常见的用法。实际上,你不必将它们命名为args
和kwargs
,那只是一种约定俗成的写法。
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 )
使用这种方式,子类并不真正知道(或关心)其超类的初始化。如果您意识到需要更改超类,则可以在不必为每个子类中的细节而感到焦虑的情况下解决问题。
super
方面找到的最有帮助的答案之一。虽然这个答案已经超过5年了,但我猜在Python 2.X中仍然是使用super
的一个很好的方法,是吗? - Amelio Vazquez-Reina注意在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
*mydict
(而不是 **mylist
),但结果会略有不同(对某些人来说可能出乎意料)。 - Tadeck*x
,对于任何映射类型,您可以使用**y
。由于字典既是可迭代的又是映射的,因此您可以选择任意一种方式。请参见https://dev59.com/dmoy5IYBdhLWcg3wYM2B。 - augurar使用*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
仅澄清如何解包参数,处理缺少的参数等。
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')