• 流畅的Python读书笔记(二)序列:元组


    活动地址:CSDN21天学习挑战赛

    流畅的Python读书笔记(二)序列:元组


    初学Python时,常常会听到被人将元组称作 不可变的列表不可变是元组的一个重要特性,但是并不是它的全部。元组还能够作为一种记录——没有字段名的记录。

    元组不仅仅是不可变的列表

    元组的不可变,是最广为人知的特性。现在主要介绍其记录的作用。如下一段代码,声明了一个point元组类型的变量,用于记录一个点的二维坐标。

    point = (3, 4)
    
    • 1

    这里的元组就充当了记录的作用。

    你可能会问。什么?就这?我用列表也可以啊。

    使用列表的确同样可以达到记录的效果,但是列表是可变序列,而元组是不可变序列。这个不可变很重要。这意味着,你不能随意修改已经创建好的元组中元素的值,也不能随意删除或添加元素,去破坏这项记录的结构。也就是说,用元组记录数据比列表更"安全"

    所以,从上面的描述中可以看出,对于比较重要的数据记录,我们最好使用元组去存储它们。

    元组拆包

    很多时候,我们会将序列中的元素取出并保存到其他变量中。如下

    point = (3, 4)
    x = point[0]
    y = point[1]
    
    • 1
    • 2
    • 3

    这样做就实现了获取元组中的元素值。但是这种写法太过冗余。元组拆包能让我们写得更为优雅。

    point = (3, 4)
    x, y = point
    
    • 1
    • 2

    实际上,元组拆包并不仅仅能够用于元组这一数据类型,元组拆包可以应用到任何可迭代对象上。唯一的硬性要求便是:需要使用相同数量的变量来接收可迭代对象拆包后的所有元素。当然,如果我们只需要拆包后的一部分元素,也可以使用*来解决,这点后面介绍。

    tips:由于拆包并不是只能用于元组,所以现在可迭代元素拆包这种表达也逐渐流行起来。

    元组拆包的使用

    • 平行赋值

    最常见的拆包方式,就是平行赋值。

    point = 3, 4
    x, y = point  #元组拆包
    
    • 1
    • 2

    还有一种元组拆包最优雅的使用,那便是交换两个变量的值:

    x, y = 3, 4
    x, y = y, x
    
    • 1
    • 2
    • 忽略不关心的值

    我们知道,Python中有一个特殊的标识符,_空白标识符,可以处理不需要的数据。

    point = (3, 4)
    #我们不关心y坐标的值
    x, _ = point
    
    • 1
    • 2
    • 3
    • *的特殊作用

      • 作为函数参数显式拆包

        • 对于一个函数fun(a, b),需要两个参数,而我们此时有一个可迭代对象x = (3, 4),刚好其中的两个元素可以作为参数传入函数中。
        fun(*x)
        
        • 1
        • 示例:
        >>> divmod(20, 8)
        (2, 4)
        >>> t = (20, 8)
        >>> divmod(*t)
        (2, 4)
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • 用来处理拆包后多余的元素

        • 示例
        >>> a, b, *rest = range(5)
        >>> a, b, rest
        (0, 1, [2, 3, 4])
        >>> a, b, *rest = range(3)
        >>> a, b, rest
        (0, 1, [2])
        >>> a, b, *rest = range(2)
        >>> a, b, rest
        (0, 1, [])
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9

        对于上面那个前面加上了*的变量rest,它会容纳下剩余所有的元素。这个加了*的变量我们先称其为特殊变量。

        • 特殊变量(带*前缀的变量)使用规则

          1. 在平行赋值中,特殊变量只能出现一个,即不能出现a, b, *rest1, *rest2 = range(10)这样的代码,因为特殊变量超过了1个;

          2. 特殊变量可以出现在等式左值中的任意位置

          >>> a, *rest, b = range(5)
          >>> a, rest, b
          (0, [1, 2, 3], 4)
          
          • 1
          • 2
          • 3

    嵌套元组拆包

    本来想自己创造一个简单的例子,但是还是为了深入理解,使用书上稍微复杂一点的例子。

    metro_areas = [
        ('Tokyo','JP',36.933,(35.689722,139.691667)),
        ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
        ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
        ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
        ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
    ]
    
    print('{:15} | {:^9} | {:^9}'.format('', 'lat.', 'long.'))
    fmt = '{:15} | {:9.4f} | {:9.4f}'
    for name, cc, pop, (latitude, longitude) in metro_areas:  
        if longitude <= 0:  
            print(fmt.format(name, latitude, longitude))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    上面代码并不难,我们只抽取涉及到元组拆包的部分,由于使用了循环,我们分析第一次循环的拆包过程。

    name, cc, pop, (latitude, longitude) = metro_areas[0]
    
    • 1

    name指城市名,cc指城市所在国家,pop指人口数,latitudelongitude分别指经度和纬度。

    关于拆包的一点个人理解

    从开始的平行赋值处开始:

    point = (3, 4)
    x, y = point
    
    • 1
    • 2

    拆包的主要目的,是将一个数据集合拆开,将集合中的元素抽取出来并将它们单独作为个体来使用。我们对上面的代码做点小的改动。

    point = (3, 4)
    (x, y) = point
    
    • 1
    • 2

    对的,将等号左值用括号括起来,这样拆包的代码可以看成这样

    (x, y) = (3, 4)
    
    • 1

    通过观察,可以发现,等号左值和右值具有相同的结构,由于具有相同的结构,Python解释器便能够将“包”中的元素对应到变量中。

    同样的,嵌套拆包也可以做这样的处理。

    仍然使用前面出现过的代码:

    name, cc, pop, (latitude, longitude) = ('Tokyo','JP',36.933,(35.689722,139.691667))
    
    • 1

    很显然, 将等号左值加上括号后,等号两侧结构相同,解释器便能够对其进行拆包赋值。

    (name, cc, pop, (latitude, longitude)) = ('Tokyo','JP',36.933,(35.689722,139.691667))
    
    • 1

    参考资料

    • 流畅的Python
  • 相关阅读:
    接口请求加签名
    你适合做自动化测试吗?
    (附源码)springboot医疗管理系统 毕业设计 015221
    区间信息维护与查询【树状数组 】 - 原理2 多维树状数组
    DevOps(十二)Jenkins实战之Web发布到远程服务器
    JVM 配置参数 -D,-X,-XX 的区别
    用Python开发QQ机器人详解
    http发送和接收图片json文件
    筋膜枪控制、驱动方案推荐:有感方波、无感方波控制
    .NET的PLC帮助类
  • 原文地址:https://blog.csdn.net/m0_52339560/article/details/126337377