**(双星号/星号)和*(星号/星号)对参数有什么作用?

在以下方法定义中,***param2什么?

def foo(param1, *param2):
def bar(param1, **param2):
别坑我2020/06/05 17:56:21

该表非常适合在函数构造和函数调用中使用*使用**

            In function construction         In function call
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

这实际上只是用来总结Lorin Hochstein的答案,但我发现它很有帮助。

相关:在Python 3中扩展了star / splat运算符的用法

小卤蛋2020/06/05 17:56:21

这个例子可以帮助您记住*args**kwargs甚至super可以立即在Python中继承。

class base(object):
    def __init__(self, base_param):
        self.base_param = base_param


class child1(base): # inherited from base class
    def __init__(self, child_param, *args) # *args for non-keyword args
        self.child_param = child_param
        super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg

class child2(base):
    def __init__(self, child_param, **kwargs):
        self.child_param = child_param
        super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg

c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1
十三2020/06/05 17:56:20
  • def foo(param1, *param2):是一种方法,可以接受任意数量的值*param2
  • def bar(param1, **param2): 是一种可以使用键接受任意数量的值的方法 *param2
  • param1 是一个简单的参数。

例如,在Java中实现varargs的语法如下:

accessModifier methodName(datatype arg) {
    // method body
}
斯丁前端2020/06/05 17:56:20

TL; DR

它包传递给函数的参数将listdict分别在函数体中。当定义这样的函数签名时:

def func(*args, **kwds):
    # do stuff

可以使用任意数量的参数和关键字参数来调用它。非关键字参数打包到args函数体内调用的列表中,而关键字参数打包到kwds函数体内调用的dict中

func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])

现在函数体,当函数被调用里面,有两个局部变量,args这是一个有值列表["this", "is a list of", "non-keyword", "arguments"]kwds它是一个dict具有价值{"keyword" : "ligma", "options" : [1,2,3]}


这也可以反向进行,即从呼叫方进行。例如,如果您将函数定义为:

def f(a, b, c, d=1, e=10):
    # do stuff

您可以通过解压缩调用范围中的迭代器或映射来调用它:

iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)
村村2020/06/05 17:56:20

我想举一个别人没有提到的例子

*也可以打开发电机包装

Python3文档中的一个示例

x = [1, 2, 3]
y = [4, 5, 6]

unzip_x, unzip_y = zip(*zip(x, y))

unzip_x将为[1、2、3],unzip_y将为[4、5、6]

zip()接收多个可初始化的参数,并返回一个生成器。

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))
卡卡西Near2020/06/05 17:56:20

从Python文档中:

如果位置参数多于形式参数槽,则引发TypeError异常,除非存在使用语法“ * identifier”的形式参数;否则,将引发TypeError异常。在这种情况下,该形式参数将接收包含多余位置参数的元组(如果没有多余位置参数,则为空元组)。

如果任何关键字参数与形式参数名称都不对应,则除非存在使用语法“ ** identifier”的形式参数,否则将引发TypeError异常;否则,将引发TypeError异常。在这种情况下,该形式参数将接收包含多余关键字参数的字典(使用关键字作为键,并将参数值用作对应的值),或者如果没有多余的关键字参数,则接收一个(新的)空字典。

小卤蛋2020/06/05 17:56:19

* 表示将可变参数作为元组接收

** 表示将可变参数作为字典接收

使用方式如下:

1)单*

def foo(*args):
    for arg in args:
        print(arg)

foo("two", 3)

输出:

two
3

2)现在 **

def bar(**kwargs):
    for key in kwargs:
        print(key, kwargs[key])

bar(dic1="two", dic2=3)

输出:

dic1 two
dic2 3
小小2020/06/05 17:56:19

***在函数参数列表中有特殊用法。* 表示该参数是一个列表,并且**表示该参数是一个字典。这允许函数接受任意数量的参数