Python中的参数解包:`*`表达式和 `**`表达式

目录

  • 1.参数解包:方法调用中的*表达式**表达式
  • 2.参数解包:方法定义中的*表达式**表达式
  • 3.在元组,列表,集合和字典中解包
  • 4.Extended Unpacking:赋值表达式左边的*表达式

1.参数解包:方法调用中的*表达式**表达式

如果语法*表达式出现在函数调用中,则该表达式必须是可迭代的。
这些可迭代集合的元素被视为附加的位置参数。
对于调用f(x1, x2, *y, x3, x4),如果y等于序列[y1,...,yM],则等效于调用f(x1, x2, y1, ..., yM, x3, x4)

如果函数调用中出现语法**表达式,则该表达式的值必须为“映射”,其内容被视为附加的关键字参数。
如果一个关键字已经存在(作为一个明确的关键字参数,或来自另一个解包),则会引发“ TypeError”异常。

关于参数顺序的说明:* 表达式可以出现在显式关键字参数之后,并在关键字参数和任何** 表达式参数之前被处理。而在一般函数的显式参数调用中,位置参数必须放在关键字参数之前。例如:

def func(a, b ,c):
    print(a, b, c)

func(c=3, 1, 2)                # SyntaxError: positional argument follows keyword argument
func(c=3, *(1,2))              # OK. 1 2 3
func(c=3, **dict(a=1,b=2))     # OK. 1 2 3
func(c=3, *(1,), **dict(b=2))  # OK. 1 2 3

2.参数解包:方法定义中的*表达式**表达式

如果存在形式* identifier,则将其初始化为接收任何其余位置参数的元组,默认为空元组。

如果存在形式** identifier,则将其初始化为一个新字典,该字典将接收任何其余的关键字参数,默认为一个新的空字典。

所以 *args其实是一个元组!

让我们来看一个例子:

def func(*args, **kwargs):
    print(args)
    print(kwargs)
    print(locals())

func(1, a=2)

# output:
#   (1,)
#   {'a': 2}
#   {'kwargs': {'a': 2}, 'args': (1,)}

单元素元组的语法看起来有点奇怪。不过习惯就好了。

仅需使用尾部逗号就能创建单个元组(也称为单例);在所有其他情况下,逗号是可选的。没有尾部逗号的单个表达式不会创建元组,而是会产生该表达式的值。

3.在元组,列表,集合和字典中解包

>>> *range(4), 4
(0, 1, 2, 3, 4)
>>> [*range(4), 4]
[0, 1, 2, 3, 4]
>>> {*range(4), 4}
{0, 1, 2, 3, 4}
>>> {'x': 1, **{'y': 2}}
{'x': 1, 'y': 2}

在字典中,后一个值将始终覆盖前一个值。

  • 注意,我们也可以这样理解

    • *可迭代集合解包算子
    • **字典解包算子

4.Extended Unpacking:赋值表达式左边的*表达式

赋值表达式左侧的元组(或列表)至多可以包含一个带有单个星号的表达式(称为“星号”表达式,而列表中的其他表达式则称为“强制性”)。

强制表达式的值将根据赋值表达式右边元组(或列表)中对应的元素位置被分配。

例如,如果seq是可切分的序列,且seq具有至少2个元素,则以下所有赋值均等效:

a, *b, c = seq
[a, *b, c] = seq
a, b, c = seq[0], list(seq[1:-1]), seq[-1]
  • seq[0]保证赋值给a
  • seq[-1]保证赋值给c
  • 其余元素则赋值给b,b一定是个列表。
  • 如果 len(seq)==2,b为空列表

如果星号表达式赋值的长列表,那么会报错:

*a = range(5)  # SyntaxError: starred assignment target must be in a list or tuple

这样就可以了:

*a, = range(5)  # OK
a: [0, 1, 2, 3, 4]

该建议也适用于隐式赋值中的元组,例如在for语句中:

for a, *b in [(1, 2, 3), (4, 5, 6, 7)]:
    print(b)

# output:
#   [2, 3]
#   [5, 6, 7]

更多的例子可以参考 stack overflow: Unpacking, Extended unpacking, and nested extended unpacking

Ref:
http://yaoyao.codes/python/2016/09/25/python-starred-expression
The Python Language Reference - 6.3.4. Calls
The Python Language Reference - 8.6. Function definitions
The Python Language Reference - 6.14. Expression lists
PEP 448 – Additional Unpacking Generalizations
PEP 3132 – Extended Iterable Unpacking

原文地址:https://www.cnblogs.com/tech-stronger/p/12333715.html

时间: 2024-08-02 05:48:32

Python中的参数解包:`*`表达式和 `**`表达式的相关文章

python 输入参数解包,模块导入,接收IO输入参数

#coding=utf-8 from sys import argv script,first,second,third = argv print "the script is=",script print "the first is=",first print "the second is=",second print "the third is=",third """ 执行方法 D:\>

python之参数解包

# 参数解包:将整个list当做参数传给函数 list = [1, 2, 4] def add_fn(a, b, c): return a + b + c sum = add_fn(*list) print("参数解包:", sum) 运行结果: 参数解包: 7

转载:唐磊的个人博客《python中decorator详解》【转注:深入浅出清晰明了】

转载请注明来源:唐磊的个人博客<python中decorator详解> 前面写python的AOP解决方案时提到了decorator,这篇文章就详细的来整理下python的装饰器--decorator. python中的函数即objects 一步一步来,先了解下python中的函数. def shout(word='hello,world'):     return word.capitalize() + '!'print shout()#输出:Hello,world!#跟其他对象一样,你同样

Python中dict详解

yangyzh Python中dict详解 python3.0以上,print函数应为print(),不存在dict.iteritems()这个函数. 在python中写中文注释会报错,这时只要在头部加上# coding=gbk即可 #字典的添加.删除.修改操作dict = {"a" : "apple", "b" : "banana", "g" : "grape", "o&qu

python中函数参数的引用方式

值传递和引用传递时C++中的概念,在python中函数参数的传递是变量指向的对象的物理内存地址!!! python不允许程序员选择采用传值还是传引用.Python参数传递采用的肯定是"传对象引用"的方式.这种方式相当于传值和传引用的一种综合.如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过"传引用"来传递对象.如果函数收到的是一个不可变对象(比如数字.字符或者元组)的引用,就不能直接修改原始对象--相当于通过"传值

Python 中的时间处理包datetime和arrow

Python 中的时间处理包datetime和arrow 在获取贝壳分的时候用到了时间处理函数,想要获取上个月时间包括年.月.日等 # 方法一: today = datetime.date.today() # 1. 获取「今天」 first = today.replace(day=1) # 2. 获取当前月的第一天 last_month = first - datetime.timedelta(days=1) # 3. 减一天,得到上个月的最后一天 print(last_month.strfti

Python中模块(Module)和包(Package)的区别

1. 模块(Module) 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在Python中,一个.py文件就称之为一个模块(Module). 使用模块有什么好处? 最大的好处是大大提高了代码的可维护性.其次,编写代码不必从零开始.当一个模块编写完毕,就可以被其他地方引用.我们在编写程序的时候,也经常引用其他模

Python中的参数是如何传递的?

本文和大家分享的主要是python中参数传递方式相关内容,一起来看看吧,希望对大家学习python有所帮助. 位置参数 调用函数时,根据函数定义的参数位置来传递参数. 1 def right_triangle_area(a,b):2     return 1/2*a*b3 4 print(right_triangle_area(3,4))5 # 位置参数传递 求直角三角形面积,a.b分别为两条直角边,这里调用函数时使用的是位置参数传递.在位置参数传递中,参数的顺序是不可改变的. 关键词参数传递

(转)python中的参数:*args和**kwargs

def foo(*args, **kwargs):print 'args = ', argsprint 'kwargs = ', kwargsprint '---------------------------------------'if __name__ == '__main__':foo(1,2,3,4)foo(a=1,b=2,c=3)foo(1,2,3,4, a=1,b=2,c=3)foo('a', 1, None, a=1, b='2', c=3) 输出结果如下:args = (1,