python解包 --*args **kwargs

任何可迭代对象都支持解包,可迭代对象包括元组、字典、集合、字符串、生成器等实现了_next__方法的一切对象。
列表:

>>> a, b, c = [1,2,3]
>>> a
1
>>> b
2
>>> c
3

元组:

>>> a,b,c = (1,2,3)
>>> a
1
>>> b
2
>>> c
3

字符串

>>> a,b,c = "abc"
>>> a
'a'
>>> b
'b'
>>> c
'c'

字典:

>>> a,b,c = {"a":1, "b":2, "c":3}
>>> a
'a'
>>> b
'b'
>>> c
'c'
字典解包后,只会把字典的 key 取出来,value 则丢掉了。

解包应用实例:-----多变量赋值, 本质上也是自动解包过程

>>> a, b = 1, 2
>>> a
1
>>> b
2

所以写代码的时候需要特别注意。在 Python 中,交换两个变量非常方便,本质上也是自动解包过程。

>>> a, b = 1, 2
>>> a, b = b, a
>>> a
2
>>> b
1

使用"*表达式"来分解任意长度的可迭代对象中的元素,返回list对象

在 Python2 中,如果等号左边变量的个数不等于右边可迭代对象中元素的个数,是不允许解包的。但在 Python3 可以这么做了。

>>> a, b, *c = [1,2,3,4]
>>> a
1
>>> b
2
>>> c
[3, 4]
>>>

这种语法就是在某个变量面前加一个星号,而且这个星号可以放在任意变量,每个变量都分配一个元素后,剩下的元素都分配给这个带星号的变量。

*a, b, c = (1, 2, 3, 4)
a
Out: [1, 2]

*表达式语法使得你的代码写起来更简洁,比如上面例子,在 Python2 中该怎么操作呢?

>>> n = [1,2,3,4]
# 使用切片操作
>>> a, b, c = n[0], n[1:-1], n[-1]
>>> a
1
>>> b
[2, 3]
>>> c
4

应用实例:
1、迭代变长的元组序列

records = [
    ('foo', 1, 2),
    ('bar', 'hello'),
    ('foo', 3, 4)
]

def do_foo(x, y):
    print('foo', x, y)

def do_bar(s):
    print('bar', s)

for tag, *args in records:
    if tag == 'foo':
        do_foo(*args)
    elif tag == 'bar':
        do_bar(*args)

2、与字符串处理操作结合

line = 'nobody:*"-2:-2:Unprivileged User:/var/empty:/usr/bin/false'
uname, *fields, homedir, sh = line.split(':')
uname
Out[7]: 'nobody'
homedir
Out[8]: '/var/empty'
sh
Out[9]: '/usr/bin/false'

函数调用时的解包操作:函数调用时,有时你可能会用到两个符号:星号* 和 双星号**。
>>> def func(a,b,c):
...     print(a,b,c)
>>> func(1,2,3)
1 2 3

func 函数定义了三个位置参数 a,b,c,调用该函数必须传入三个参数,除此之外,你也可以传入包含有3个元素的可迭代对象,

>>> func(*[1,2,3])
1 2 3
>>> func(*(1,2,3))
1 2 3
>>> func(*"abc")
a b c
>>> func(*{"a":1,"b":2,"c":3})
a b c

函数被调用的时候,使用星号 * 解包一个可迭代对象作为函数的参数。字典对象,可以使用两个星号,解包之后将作为关键字参数传递给函数

>>> func(**{"a":1,"b":2,"c":3})
1 2 3
** 符号作用的对象是字典对象,它会自动解包成关键字参数 key=value 的格式:
>>> func(a=1,b=2,c=3)
1 2 3

总结一下:

一个星号可作用于所有的可迭代对象,称为迭代器解包操作,作为位置参数传递给函数;
两个星号只能作用于字典对象,称之为字典解包操作,作为关键字参数传递给函数。

使用 *和 ** 的解包的好处是能节省代码量,使得代码看起来更优雅,不然你得这样写:

>>> d = {"a":1, "b":2, "c":3}
>>> func(a = d['a'], b=d['b'], c=d['c'])
1 2 3
>>>

在 Python3.5,也就是 PEP 448 对解包操作做了进一步扩展, 在 3.5 之前的版本,函数调用时,一个函数中解包操作只允许一个* 和 一个**。从 3.5 开始,在函数调用中,可以有任意多个解包操作,例如:

Python 3.4 中 print 函数 不允许多个 * 操作
>>> print(*[1,2,3], *[3,4])
  File "<stdin>", line 1
    print(*[1,2,3], *[3,4])
                    ^
SyntaxError: invalid syntax
>>>
再来看看 python3.5以上版本,可以使用任意多个解包操作
>>> print(*[1], *[2], 3)
1 2 3

从 3.5 开始可以接受多个解包,于此同时,解包操作除了用在函数调用,还可以作用在表达式中。

>>> *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}

新的语法使得我们的代码更加优雅了,例如拼接两个列表可以这样:

>>> list1 = [1,2,3]
>>> list2 = range(3,6)
>>> [*list1, *list2]
[1, 2, 3, 3, 4, 5]
>>>

可不可以直接用 + 操作呢?不行,因为 list 类型无法与 range 对象相加,你必须先将 list2 强制转换为 list 对象才能做 +操作。

再来看一个例子:如何优雅的合并两个字典

>>> a = {"a":1, "b":2}
>>> b = {"c":3, "d":4}
>>> {**a, **b}
{'a': 1, 'b': 2, 'c': 3, 'd': 4}

在3.5之前的版本,你不得不写更多的代码:

>>> import copy
>>>
>>> c = copy.deepcopy(a)
>>> c.update(b)
>>> c
{'a': 1, 'b': 2, 'c': 3, 'd': 4}

最后总结一下:

1、自动解包支持一切可迭代对象
2、python3中,支持更高级的解包操作,用星号操作使得等号左边的变量个数可以少于右边迭代对象中元素的个数。
3、函数调用时,可以用 * 或者 ** 解包可迭代对象,作为参数传递
python3.5,函数调用和表达式中可支持更多的解包操作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容

  • 〇、前言 本文共108张图,流量党请慎重! 历时1个半月,我把自己学习Python基础知识的框架详细梳理了一遍。 ...
    Raxxie阅读 18,942评论 17 410
  • python中的解包你可以这个样子来理解:一个list是一个整体,想把list中的每一个元素都当成一个个个体剥离出...
    龙皓晨阅读 1,159评论 0 1
  • 好久都没有吃黄豆了。以前我很爱吃黄豆:打豆浆,或熬稀饭吃。后来有一次我听人家说转基因黄豆,说转基因黄豆的形状特别的...
    目光向上阅读 446评论 0 0
  • CPA,“注册会计师” CPA 是注册会计师(Certified Public Accountant)的英文缩写,...
    哈局回复阅读 444评论 0 0
  • 姓名:陶金 公司:深圳保民利信息科技有限公司 【日精进打卡第128天】 【知-学习】 1、《六项精进》通遍1遍,共...
    陶金保民利阅读 178评论 0 0