【Python拆包装包】拆包装包的一些应用场景和细节

Python拆包与装包

很多关于Python的网课都没有这方面的内容,或者讲的不详细,CSDN上的相关帖子写的也是稀烂,要么就是搬运的排版不好,看都不想看,在这总结一下,虽然我写python也不多,有些场景我也用的很少,但是以后还能回来看一看或者补充补充。

如果想看外国一些好的论坛或者技术网站,可以在必应上选择国际版或者全英文查找就可以看到,比如stackoverflow,geekforgeeks之类的。

拆包

在程序编写中有一句话:存在即合理

那么理解语法最好的方法就是在需求中,在遇到实际问题时理解。

应用场景1:取元组中的数据

>>> a = ('BUPT', 5000, 'TELE COM')
>>> (college, students, major) = a
>>> college
'BUPT'
>>> students
5000
>>> major
'TELE COM'

应用场景2:交换值

众所周知,在C中交换两数有三种方法,但是任何情况都正确的只有一种,需要多定义一个变量保存其中一个值。而在Python中可以利用元组来实现交换:

a = 1 
b = 2 
a, b = b, a
print("a = %d, b = %d" % (a, b))
##########################
a = 2, b = 1

如果你是从其他语言过来学Python,那肯定是觉得:“哦,牛批,还有贼种操作!”

a, b = b, a这一步其实拆包装包都有。

右侧的b, a其实是元组(b, a),这是装包

左侧的a, b就是拆包操作,你写成(a, b) = (b, a)也可以。

应用场景3:取部分数据

比如,在一个元组中我只想要头尾数据:

a = (1, 2, 3, 4)
x, *_, z = a 
print("x = %d" % x)
print("_ = " + str(_))
print("z = %d" % z)
####################
x = 1
_ = [2, 3]
z = 4

可以看到,虽然这样子看起来很像是指针,取出头尾,中间部分存在了一个列表中,但是拆包非常灵活,可以试试其他组合都是可行的。

应用场景4:列表变元组

当然可以用tuple将一个列表初始化为元组,但是这是一种技巧

a = [1, 2, 3, 4]
print("data in a:%d %d %d %d" % a) 
############################
print("data in a:%d %d %d %d" % a)
TypeError: %d format: a number is required, not list

很显然,%后面跟的一定得是一个元组,但是a是一个列表,这时就要用到拆包把列表拆了,列表的拆包和元组一样。

a = [1, 2, 3, 4]
print("data in a:%d %d %d %d" % (*a,))
############################
data in a:1 2 3 4

**这里还有个小坑:**后面字典的拆包总让人感觉拆包就像宏函数,但其实根本不是,在拆包后再构成元组时,因为只有一个数据在元组中必须加上逗号,否则:

print("data in a:%d %d %d %d" % (*a))
                                     ^
SyntaxError: can't use starred expression here

当然既然列表也能拆包,也可以用拆包将列表变为元组:

In [15]: a = [1, 2, 3, 4]

In [16]: b = (*a,)

In [17]: b
Out[17]: (1, 2, 3, 4)

应用场景5:元组拆包后当作函数参数

def ret(x, y): 
    return x*y 

z = (10, 5)

print(ret(*z))
#####################
50

装包

应用场景1:函数返回多值,构成元组

#接拆包应用场景1
a = ('BUPT', 5000, 'TELE COM')
college, students, major = a 
def ret(x, y): 
    return y,x 

print(ret(10, 20))
#####################
(20, 10)

可以看到ret函数实现了数值交换,虽然没有显式的返回元组,可以看到打印出的是元组,当然也可以显式地返回元组,结果是一样的,这就是装包。

(20, 10)def ret(x, y): 
    return (y,x)

print(ret(10, 20))
###############
(20, 10)

应用场景2:函数参数数量不定

有时候,一个函数的参数数量不可预知,这时Python装包的作用就体现出来了。

def fun(*arg):
    print(type(arg))

    print(arg)

fun(1, 2, 3, 4)
######################
<class 'tuple'>
(1, 2, 3, 4)

这里原理没什么好理解的,硬是想理解可以把arg看作像是C里的指针,把参数装入了arg所指的内存,同时arg是一个元组。

还可以这样:

def fun(**kwarg):
    print(type(kwarg))

    print(kwarg)

fun(name="xiaoming", age=18)
#############################
<class 'dict'>
{'name': 'xiaoming', 'age': 18}

这个看着像二级指针的东西就是向函数传键值对数量不定的字典的方法。注意参数的形式:a=b,也叫做keword arguments,但是和一般的参数不同的是这里a就是键,在字典中是串,b就是a对应的值,在函数中kwargs就可以当作一个字典用。

举个C的例子:

#include<stdio.h>
#include<stdlib.h>

int calc_sum(int*,int);

int main(int argc, char **argv){
        
    int i,a[argc-1];
    for(i=1;i<argc;i++)
        a[i-1]=atoi(argv[i]);

    printf("sum of a is %d\n", calc_sum(a,argc-1));

    return 0;
}

int calc_sum(int *A,int k){ 
    int i,sum=0;
    for(i=0;i<k;i++)
        sum+=A[i];
    return sum;
}
//
./main 10 1 2
13

char **argv:argv是一个二级指针,其实是一个指针数组的名字,数组中保存char*指针,类似python,**kwargs保存数据的指针,指针中存的是key,索引key得到values。

int *A:A是一个一级指针,其实在函数参数中一般是一个数组名,其中保存多个数据。

这些*在函数参数和其他地方的差异:

在汉数参数中*就代表这是一个指针,数组,字典云云。

但是在其他语句中单用*,**。效果不一样,在Python中使用**,相当于就地展开,怎么展开:

In [4]: ret(**a)
lisi is an adult

In [5]: a = {'name':'lisi', 'age':19}

In [6]: def ret(name, age):
   ...:     if age>=18:
   ...:         print(f'{name} is an adult')
   ...:     else:
   ...:         print(f'{name} is a child')
   ...: 

In [7]: ret(**a)
lisi is an adult

一个字典变成了这样:

ret(name='lisi', age=19)

用print函数验证一下:

In [8]: print(**a)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [8], in <cell line: 1>()
----> 1 print(**a)

TypeError: 'name' is an invalid keyword argument for print()
#说明print中的参数是这样的
print(name='lisi', age=19)
#显然这两个不是print的参数,所以报错

那么字典前面只有一个*呢?

得到结果是健:

In [17]: k1, k2 = a

In [18]: k1
Out[18]: 'name'

In [19]: k2
Out[19]: 'age'

In [20]: a[k1]
Out[20]: 'lisi'

In [21]: a[k2]
Out[21]: 18
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明光桥北修狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值