*args 和 **kwargs 是啥意思? [复制]

Posted

技术标签:

【中文标题】*args 和 **kwargs 是啥意思? [复制]【英文标题】:What do *args and **kwargs mean? [duplicate]*args 和 **kwargs 是什么意思? [复制] 【发布时间】:2010-09-22 04:09:01 【问题描述】:

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

你如何有效地使用它们?

【问题讨论】:

只是小时和千瓦时的一个糟糕的双关语。 这篇文章对深入理解主题非常有用:agiliq.com/blog/2012/06/understanding-args-and-kwargs 【参考方案1】:

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

例如,如果你想编写一个返回所有参数总和的函数,无论你提供多少,你都可以这样写:

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

它可能更常用于面向对象的编程中,当您重写一个函数并希望使用用户传入的任何参数调用原始函数时。

您实际上不必称它们为 argskwargs,这只是一个约定。是 *** 发挥了作用。

Python 官方文档有a more in-depth look。

【讨论】:

不客气,不客气。也让我迷惑了一阵子。如果你认真地接触 Python,我衷心推荐 Mark Lutz 的“Programming Python”。 也许链接到深入解释这一点的教程,每个人都应该阅读:docs.python.org/tutorial/… @AliAfshar:你的链接是我所需要的,应该是自己的答案。谢谢! @PaulD.Waite:没问题。我想知道有多少菜鸟通过尝试使用您的代码发现了这个错误,但他们告诉自己“我一定是在这里做错了,这个答案有很多选票”;)我的另一个赞成票,因为非常清晰,非常好。【参考方案2】:

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

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 并不真正知道(或关心)超类初始化是什么。如果您意识到您需要更改超类,您可以解决问题,而无需费心处理每个子类中的细节。

【讨论】:

这是我找到的关于如何使用 super 的最有用的答案之一。这个答案已经超过 5 年了,但我想这仍然是在 Python 2.X 中使用super 的好方法,对吗? 是的,仍然可以这样做。 谢谢,但如果你能提供一些真实的例子,为什么以及何时使用它,那就太好了。在上面的例子中,如果我这样做会发生什么?【参考方案3】:

注意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

【讨论】:

你实际上也可以*mydict(不是**mylist),但结果会略有不同(有些人意想不到)。 简单、简洁、易于理解的示例来说明这一点。我最喜欢的答案! @Tadeck 您可以对任何可迭代的对象执行*x,对任何映射类型执行**y。由于 dict 既是可迭代的又是映射的,你可以做任何一个。另见***.com/questions/8601268/…【参考方案4】:

*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

【讨论】:

【参考方案5】:

只是为了阐明如何解包参数,并处理丢失的参数等。

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

【讨论】:

以上是关于*args 和 **kwargs 是啥意思? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

python中**是啥意思?

python中*args和**kwargs学习

python里面args作为参数但是方法体里面没有调用,那这个args的作用是啥?

前言,复习想直接看源代码,这里先分享下,*args和**kwargs他们都是什么意思

Python面试题之这两个参数是什么意思:*args,**kwargs?我们为什么要使用它们?

参数arg、*args、**kwargs三个的区别