理解和使用python中的拆包会让我们的代码变得流畅,不仅对自己的手关节有好处,也使看官觉得很赏心悦目,既然拆包这么香那就抓紧用起来吧。
在C,C++和Java语言中如果想交换两个变量的值就必须用到第三个临时变量,但是在python中我们竟然可以做到不用经过第三方的手直接进行交换了,即省去了第三个变量又尽显优雅,那么他是如何实现的呢。
a = 1
b = 2
a, b = b, a
我们先说python中一个重要的数据结构,那就是元组
,在元组( )
可以省略,那么上面的a, b = b, a
等式右边的b, a
就自行构成了一个元组。
所以左边就变成了对元组的拆包过程。直接交换变量的实质就是一个打包和拆包的过程。
1、元组的拆包
tup = (1, 2, 3)
# 方式一
a, b, c = tup # 要求元组内的个数与接收的参数个数相同
print(a, b, c)
结果如下:
1 2 3
# 方式二
print(*tup) # 使用*进行拆包,结果同上
add(*tup)
如下方式是错误的
a, b, c = *tup
这两种方式分别在什么情况下使用呢?
下面介绍一点稍微复杂一点的拆包
tup = (1, 2, 3, 4, 5, 6)
比如说这个又6个数据的元组,我们感兴趣的只有开头和结尾的数据,不想要中间的数据,那需要像上面那样弄6个参数来接受吗?
a, *_, b = tup # 中间的数据被打包到了 _ 中,我们只获取到了开头和结尾的数据
从上面这个例子中我们可以看到,*
这个符号既可以用来拆包也可以用来打包。可以把任意多的数据打包起来。拆包过程中如果使用了
* 号,我们只能提取开头或者结尾的感兴趣数据。
还有下面这种,多层包含的拆包。(也可以包含列表和字典的数据结构)
tup = (1, 2, (3, 4, 5), 6)
拆包
a, b, c, d = tup
结果如下:
1 2 (3, 4, 5) 6
c就是中间哪个元组了。如果想进一步拆包,重复上述步骤即可。
我们看到,多余的3, 4, 5这三个参数被打包到了*args
这个参数中去了。
2、列表的拆包与元组一样
3、字典的拆包
其实用法与元组和列表一样,只不过字典拆包得到值是key
而已。
dick = {"张三":18, "李四":22, "王五":24}
a, b, c = dick
张三 李四 王五
4、函数参数的装包与拆包
我们会经常看到如下形式定义的函数
def func(a, b, *args):
print(a, b)
print(type(args))
print(args)
如果我们这样func(1, 2, 3, 4, 5, 6)调用函数,结果如下:
1 2
(3, 4, 5, 6)
从结果出发我们可以得出如下结论:
我们还可以这样传参数,
lis = (1, 2, 3, 4, 5, 6)
func(*lis) # 回应上面方式二的使用情况
上面可以说是拆包的初相识,下面我们在来看看它的应用场景还有那些。
stars = ("黎明", "华仔", "郭富城", "张学友")
print("四大天王:%s, %s, %s, %s" % stars)
如果你写成下面这样的,会使什么感受。太不pythonic
了吧。
stars = ("黎明", "华仔", "郭富城", "张学友")
print("四大天王:%s, %s, %s, %s" % (stars[0], stars[1], stars[2], stars[3]))
再来看看列表的打印。你们可能感觉列表和元组的结果一样,但事实往往和我们想的它就不一样。
stars = ["黎明", "华仔", "郭富城", "张学友"]
print("四大天王:%s, %s, %s, %s" % stars)
报错,我只想说一句fucker,具体的原因我也没查到。猜测是%后面不接受这种长度或者数据可变的数据类型作为参数,当然只是猜测。
怎么解这个BUG呢,
stars = ["黎明", "华仔", "郭富城", "张学友"]
print("四大天王:%s, %s, %s, %s" % (*stars,))
为什么会这样呢,我不能只告诉你结果就完事了,那样没有意义,虽然我们不能把它的内裤拔下来一看究竟,那也得尝试拔他最外面的一层皮。
(*stars,)
到底做了什么。一定注意括号内的,
绝对不能丢。(*stars,)
到底是何方神圣呢,看下面结果,这个操作直接把列表变成了一个元组,不是又学到了,列表转换成元组的又一种方法
。
还可以这么做,不过道理也是一样的:
print("四大天王:%s, %s, %s, %s" % tuple(stars))
即元组与列表的打印拆包中总结,只能默认拆包元组,如果是列表就先转换成元组在拆包。