• 元组啊,不就是不可变的列表吗?


    B站|公众号:啥都会一点的研究生

    相关阅读

    整理了几个100%会踩的Python细节坑,提前防止脑血栓
    整理了十个100%提高效率的Python编程技巧,更上一层楼
    Python-列表,从基础到进阶用法大总结,进来查漏补缺
    Python-元组,从基础到进阶用法大总结及与列表核心区别,进来查漏补缺
    Python-字典,从基础到进阶用法大总结,进来查漏补缺
    Python-集合,从基础到进阶大总结,进来查漏补缺
    这些包括我在内都有的Python编程陋习,趁早改掉
    Python可变类型的坑,不要再踩了
    列表推导式,Python中最好的特性?可读性?
    元组啊,不就是不可变的列表吗?
    订阅专栏 ===> Python

    问:元组是什么

    答:呃,呃,内个,嗷,不就是“不可变的列表”嘛。

    这个概括对吗?不能说对错,只能说概括不完全,元组除开用作不可变的列表,另一个常被忽略但极其实用的作用是,用于没有字段名的记录,本期我试图和大家一起学习归纳元组的常用方法,争取更上一层楼

    首先来看看大家熟知的用法,用作不可变的列表,一句话概括就是,除了跟增删元素相关的方法外,元组支持列表的其他所有方法,为了方便说明,使用dir()分别查看列表与元组的内置方法与属性

    dir(list)
    # ['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', 
    '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', 
    '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', 
    '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
     '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__',
      '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 
      'remove', 'reverse', 'sort']
    
    dir(tuple)
    # ['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__dir__', 
    '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', 
    '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__',
     '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', 
     '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    使用help()则可以查看内置方法与属性的说明,知道大家十有八九不会再逐个help查看,行吧,我来吧,带大家一一查看对比列表与元组中除开object类支持的方法外的其他方法和属性,以列表为参考进行比照

    首先看属性,列表与元组都支持的有这些

    s.__add__(s2)     # 拼接,s + s2,不改变s
    s.__contains__(e) # s是否包含e,e in s
    s.__getitem__(p)  # 获取s中位置p的元素,s[p]
    s.__iter__()      # 获取s的迭代器
    s.__len__()       # 获取元素数量,len(s)
    s.__mul__(n)      # n个s的重复拼接,s * n,不改变s
    s.__rmul__(n)     # 反向拼接,n * s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后就是列表支持但元组不支持的

    s.__iadd__(s2)      # 拼接, s += s2,改变s
    s.__delitem__(p)    # 删除s中位于p的元素 del s[p]
    s.__imul__(n)       # n个s的重复拼接,s *= n,改变s
    s.__reversed__()    # 返回 s 的倒序迭代器
    s.__setitem__(p, e) # 将s中位置p的元素替换为e,s[p] = e
    
    • 1
    • 2
    • 3
    • 4
    • 5

    接着,我们再一起来看看列表与元组都支持的方法

    s.count(e) # e在s中的个数
    s.index(e) # e在s中第一次出现的位置索引
    
    • 1
    • 2

    是的,没了,紧接着看看列表支持但元组不支持的方法

    s.append(e)              # 在s尾部新增元素
    s.clear()                # 清空s所有元素,保留s对象
    s.copy()                 # 浅拷贝s
    s.extend(it)             # 将可迭代对象it追加给s
    s.insert(p, e)           # 在s的p位置之前插入元素e
    s.pop([p])               # 删除s中最后或(可选的)位于p的元素,并返回它的值
    s.remove(e)              # 删除 s 中的第一次出现的e值
    s.reverse()              # 把 s 的元素倒序排列,改变s
    s.sort([key], [reverse]) # 对s中的元素进行排序,可选的参数有键(key)和是否倒序(reverse),改变s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    OK,归纳完毕,想必大家对元组充当不可变列表,哪些可用,哪些不可用有了进一步了解,我是不会主动问大家要三连的

    接下来继续看看另一个用途,数据记录,如果仅把元组理解为不可变的列表,那所含元素的总数和对应位置似乎就变得可有可无,但若当成字段集合,那么这些信息就变得很重要了,举些例子来说明

    比如,在元组中存放直线的斜率与截距

    line_k_b = (1.0322, -10.6667) # k, b
    
    • 1

    元组同样支持存放不同类型的数据

    name, age, height, weight = ('CaiXukong', 30, 142.01, 180.02)
    
    • 1

    当数据增多时,通常还会以元组列表的形式存放并且搭配循环遍历,使用%格式运算符可以匹配元组中对应元素

    user_infos = [('ZS', '001'), ('LS', '002'), ('WW', '003')]
    
    for user_info in user_infos:
        print('%s/%s' % user_info)
        
    """
    ZS/001
    LS/002
    WW/003
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    此外,还可以使用拆包提取元素

    user_infos = [('ZS', '001'), ('LS', '002'), ('WW', '003')]
    
    for name, uid in user_infos:
        print(name)
        
    """
    ZS
    LS
    WW
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    关于拆包,最常见的就是平行赋值,比如之前的例子,把一个可迭代对象中的元素赋值到对应变量组成的元组中,对应变量组成的元组也就是说其实name, age, height, weight也为元组

    name, age, height, weight = ('CaiXukong', 30, 142.01, 180.02)
    
    • 1

    说到这里当然得提一下利用这个特性快速进行值交换的例子,我们可以使用如下方法交换两个变量的值

    b, a = a, b
    
    • 1

    然后通常搭配*运算符把一个可迭代对象拆开作为函数的参数,比如使用divmod得到10除以8的商和余数,提一嘴,其实函数返回值也是元组类型

    divmod(10, 8) # 1, 2
    
    type(divmod(10, 8)) # 
    
    • 1
    • 2
    • 3

    将10和8存入元组中并结合*运算符喂给函数同样达到目的

    data = (10, 8)
    quotient, remainder = divmod(*data)
    
    # quotient : 1
    # remainder : 2
    
    • 1
    • 2
    • 3
    • 4
    • 5

    但有时候不是对所有数据感兴趣,比如只会用到余数,那么则可以使用_占位符处理这种情况

    data = (10, 8)
    _, remainder = divmod(*data)
    
    # remainder : 2
    
    • 1
    • 2
    • 3
    • 4

    讲到这个,那如果我不感兴趣的数据很多怎么办,诶没关系,*运算符可以助你宠幸关心的数据,我们知道在Python中经常使用*args来获取不确定的参数,这个用法也被扩展到了平行赋值中,一起来看看这个例子

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

    虽然这个运算符只能出现在一个变量名之前,但是这个变量可以在赋值表达式的任意位置出现,不止尾部,比如中间和头部

    a, *middle, b = range(10)
    # 0 [1, 2, 3, 4, 5, 6, 7, 8] 9
    
    *head, b, c = range(10)
    # [0, 1, 2, 3, 4, 5, 6, 7] 8 9
    
    • 1
    • 2
    • 3
    • 4
    • 5

    元组的拆包同样也可以用于嵌套结构,比如这个例子

    *head, (b, c) = (1, 2, (3, 4)) 
    # [1, 2] 3 4
    
    • 1
    • 2

    注意了如果bc不加括号,则得到的结果完全就不同了

    *head, b, c = (1, 2, (3, 4)) 
    # [1] 2 (3, 4)
    
    • 1
    • 2

    讲完了拆包,下一个要讲的则是具名元组namedtuple,它继承了普通元组的属性,那是干嘛的呢,元组如果作为记录来用,缺少给记录的字段命名的功能。而namedtuple常用来构建一个带字段名的元组和一个有名字的类,怎么用呢,来看看这个例子

    先看第二行,创建一个具名元组需要两个参数,一个类名,一个该类各字段的名字,后者可以是由若干字符串组成的可迭代对象,或由空格分开的字段名组成的单字符串

    下一行,存放在对应字段里的数据要以一串参数的形式传入,然后便可以通过字段名或者位置来获取一个字段的信息

    from collections import namedtuple
    User = namedtuple('User', ['name', 'age', 'height', 'weight'])
    # User = namedtuple('User', 'name age height weight')
    CaiXukang = User('CaiXukang', 30, 142.01, 180.02)
    
    print(CaiXukang.weight) # 180.02
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ok,以上呢就是本期的全部内容,整理不易,有任何错误与补充欢迎在评论区指出,我是啥都生,我们下期再见。

  • 相关阅读:
    [思维]Longest Common Subsequence 2022牛客多校第8场 F
    Centos 搭建MQTT
    Python测试题12道(含答案)
    技术分享 | 接口自动化测试中如何对xml 格式做断言验证?
    原型制作的软件 Experience Design mac( XD ) 中文版软件特色
    vue - Vuex
    application/octet-stream的问题
    作为一个程序员,如何高效的管理时间?
    Linux系统编程-C++ I/O库
    基于社交网络优化的BP神经网络(分类应用) - 附代码
  • 原文地址:https://blog.csdn.net/zzh516451964zzh/article/details/127823945