所以我很难理解*args和**kwargs的概念。

到目前为止,我了解到:

*args=参数列表-作为位置参数**kwargs=dictionary-其键成为单独的关键字参数,值成为这些参数的值。

我不知道这对什么编程任务有帮助。

也许 吧:

我想输入列表和字典作为函数的参数,同时作为通配符,这样我就可以传递任何参数了?

有没有一个简单的例子来解释如何使用*args和**kwargs?

另外,我发现的教程只使用了“*”和变量名。

*args和**kwargs只是占位符吗?还是在代码中使用的是*args或**kwarg?


当前回答

在编写包装函数(如装饰器)时,*args和**kwargs是有用的一种情况,这些包装函数需要能够接受任意参数以传递给被包装的函数。例如,一个简单的装饰器,它打印被包装函数的参数和返回值:

def mydecorator( f ):
   @functools.wraps( f )
   def wrapper( *args, **kwargs ):
      print "Calling f", args, kwargs
      v = f( *args, **kwargs )
      print "f returned", v
      return v
   return wrapper

其他回答

这里是我最喜欢的使用**语法的地方之一,如Dave Webb的最后一个示例所示:

mynum = 1000
mystr = 'Hello World!'
print("{mystr} New-style formatting is {mynum}x more fun!".format(**locals()))

我不确定与仅仅使用名称本身相比,它是否非常快,但它更容易输入!

在编写包装函数(如装饰器)时,*args和**kwargs是有用的一种情况,这些包装函数需要能够接受任意参数以传递给被包装的函数。例如,一个简单的装饰器,它打印被包装函数的参数和返回值:

def mydecorator( f ):
   @functools.wraps( f )
   def wrapper( *args, **kwargs ):
      print "Calling f", args, kwargs
      v = f( *args, **kwargs )
      print "f returned", v
      return v
   return wrapper

这些参数通常用于代理函数,因此代理可以将任何输入参数传递给目标函数。

def foo(bar=2, baz=5):
    print bar, baz

def proxy(x, *args, **kwargs): # reqire parameter x and accept any number of additional arguments
    print x
    foo(*args, **kwargs) # applies the "non-x" parameter to foo

proxy(23, 5, baz='foo') # calls foo with bar=5 and baz=foo
proxy(6)# calls foo with its default arguments
proxy(7, bar='asdas') # calls foo with bar='asdas' and leave baz default argument

但由于这些参数隐藏了实际的参数名称,因此最好避免使用它们。

名称*args和**kwargs或**kw纯属惯例。这使我们更容易阅读对方的代码

使用struct模块是一个方便的地方

struct.unpack()返回一个元组,而struct.pack()使用可变数量的参数。在处理数据时,可以方便地将元组传递给strike.pack()。

tuple_of_data = struct.unpack(format_str, data)
# ... manipulate the data
new_data = struct.pack(format_str, *tuple_of_data)

如果没有这种能力,你将被迫写作

new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...)

这也意味着,如果format_str发生变化,元组的大小也发生变化,我将不得不返回并编辑这条非常长的行

使用*args和**kwargs非常有用的一个地方是子类化。

class Foo(object):
    def __init__(self, value1, value2):
        # do something with the values
        print value1, value2

class MyFoo(Foo):
    def __init__(self, *args, **kwargs):
        # do something else, don't care about the args
        print 'myfoo'
        super(MyFoo, self).__init__(*args, **kwargs)

通过这种方式,您可以扩展Foo类的行为,而不必对Foo了解太多。如果您正在对可能会更改的API进行编程,这将非常方便。MyFoo只是将所有参数传递给Foo类。