Python序列类型
序列(Sequence)是有顺序的数据列,Python 有三种基本序列类型:list, tuple 和 range 对象,序列(Sequence)是有顺序的数据列,二进制数据(bytes) 和 文本字符串(str)也是序列类型,它们是特殊序列类型,会有一些特殊的性质和操作。
在实际的使用中,我们并不直接使用序列(Sequence)类型,而是具体使用list、tuple和range对象等等,本文主要是做一个归纳、概括性的说明
序列类型
Python 的内置序列类型有:
| 类型 | 创建方法 | 可变性 | 特别方法 |
| 列表 | list() | 可变 | sort() |
| 元组 | tuple() | 不可变 | |
| 等差数列 | range() | 不可变 | 属性方法 |
| 字符串 | str() | 不可变 | 字符的方法 |
| 字节串 | bytes() | 不可变 | |
| 字节数组 | bytearray() | 可变 | |
| 内存视图 | memoryview() | 不可变 |
要注意的是,集合、字典不是序列类型,虽然字典在最新的 Python 版本中具备了元素顺序特性,但这不是一种「保证」。
可以通过
isinstance(obj, collections.Sequence)
来判定对象是不是一个序列类型。
扁平序列
扁平序列有两个特点,第一,内部存储的都是值而不是引用(或者说是内存地址);第二,内部存储的都是同一种数据类型,而且只能存储数值、字节、字符这样的基础数据类型。常见的扁平序列如字符串str、字节bytes、数组array.array、字节数组bytearray和内存视图memoryview等。
我们举一个例子,例如s1 = 'abc',这是一个创建字符序列str的命令。这条命令运行时,Python解释器会先在内存中开辟一块连续的内存空间来存储a、b和c三个字符,创建好对象后会将这块内存的首地址抛给外界,由变量s1来接收,变量s1是另一块内存,这块内存中就存储了字符串序列'abc'的内存首地址。之后如果需要使用'abc'这个对象,都是通过变量s1。当解释器读到变量s1时,发现其存储的是一个内存地址,就会直接读取这个内存地址对应数据,完成对象的访问。

容器序列
与扁平序列相对应,容器序列中存储的不是值而是对象的引用,正因为如此,容器中可以容纳任何数据类型。常见的容器序列包括列表list、元祖tuple等。
如下例子:list1 = [1,'abc',[10,20,’age']],这是一个列表。

可以看到,对于列表本身来说,其在内存中是连续的,但是列表的内存中存储的并不是值本身,而是对象(列表中元素)的引用。至于对象(列表中的元素)本身,则存储在别的内存块中,这些内存可能是连续的,也可能是不连续的,大概率是不连续的。而且,列表中不仅仅可以存储基本数据类型int、str,还可以存储列表list。
可变序列
可变序列是指可以在原内存地址上对数据进行修改的序列。这类序列包括列表list、字节数组bytearray、数组array.array,内存视图memoryview等。
列表list提供了append方法,可以在原列表内存地址上对列表进行修改:
>>> b = [1,2,3]
>>> id(b)
4352472384
>>> b.append(4)
>>> id(b) #追加了元素,但是b的地址并没有变化
4352472384
>>> b
[1, 2, 3, 4]
这里给列表增加了一个元素,但是列表的内存地址并没有发生变化。
不可变序列
不可变序列指的是不可以在原内存地址上对序列进行修改。这类序列包括字符序列str、元祖tuple、和字节序列bytes。
例如,对于字符序列str,一旦创建就无法在原内存地址上对数据进行修改,强行修改则是创建新的对象:
>>> s = 'abc'
>>> id(s)
4346120656
>>> s = '123'
>>> id(s) #s的内容和地址都变化了
4349997680
>>> s
'123'
>>> s += '4'
>>> id(s) #即使是追加,s的内容和地址也都变化了
4349376816
>>> s
'1234'
可能有人对元祖不可修改无法理解,对于容器序列来说,不可变指的是容器中每一个元素的引用不可变,而不是每一个元素的值不可变。如下面的例子:
>>> a = ('1','2',['3','4'])
# 记录元祖的内存地址
>>> id(a)
1665412226688
# 记录元祖中第一个元素的内存地址
>>> id(a[0])
140710344787616
# 修改元祖中的第一个元素,可以看到报错了,提示元祖对象不支持赋值。因为第一个元素是一个不可变对象,强行修改会创建新的对象,产生新的引用,而元祖不支持修改内部元素的引用,所以报错。
>>> a[0]='5'
Traceback (most recent call last):File "<pyshell#14>", line 1, in <module>a[0]='5'
TypeError: 'tuple' object does not support item assignment
# 记录元祖中第三个元素列表的内存地址
>>> id(a[2])
1665412212544
# 我们的元祖中第三个元素是一个list,这是一个可变的序列,使用append方法会在原内存地址上进行修改,这样保证元素中第三个元素的引用并不会发生变化,所以修改成功。
>>> a[2].append('9')
# 可以看到第三个元素列表修改成功
>>> a
(1, 2, [3, 4, 9])
# 但是第三个元素的内存地址并未发生变化
>>> id(a[2])
1665412212544
# 元祖第三个元素修改后,元祖本身的内存地址并未发生变化。
>>> id(a)
1665412226688
这个例子中,我们先创建了一个元祖(1,2,[3,4]),元祖中有三个元素1、2、[3,4],前两个都是不可变的字符序列str,通过前面的例子我们已经知道,如果对字符序列强行修改,不会改变原来的字符,而是创建新的对象。新的对象就意味着产生一个新的内存地址,这会导致元祖第一个元素的引用发生变化。这是元祖不能够接受的,所以出现报错。
然而,我们发现对创建的元祖的第三个元素进行修改,却修改成功了,原因是第三个元素是一个列表list,是一个可变序列,对其调用append方法是在原地址上对数据进行的修改,而并不会改变本身的内存地址,因此元祖第三个元素的引用不会发生变化,故而修改成功。
因此我们说对于容器序列,不可变意味着元素的引用不可变,相反,可变则意味着引用可以发生变化:
>>> a = [1,2,[3,4]]
>>> id(a)
2338191916032
>>> id(a[2])
2338200822784
>>> a[2]=5
>>> a
[1, 2, 5]
>>> id(a[2])
140710407702304
>>> id(a)
2338191916032
看见列表是可以修改元素的引用的,因为它是可变类型。
序列类型的协议
以上我们对Python中的序列类型进行了分类,接下来我们学习一下序列类型的协议。通过这一部分的学习,你会对面向对象以及常见序列类型有更加深刻的认识。
Python为可变序列和不可变序列提供了两个基类Sequence和MutableSequence,这两个基类存在于内置模块collections.abc中,与其他常见的类如int、list等不同,这两个基类都是抽象基类,抽象基类确定了序列类型的协议,所有属于序列类型的都要遵循这个抽象基类的协议。
Sequence和MutableSequence两个类的继承关系如下:

可变序列MutableSequence类继承自不可变序列Sequence类,Sequence类又继承了两个类Reversible和Collection,Collection又继承自Container、Iterable、Sized三个抽象基类。通过这个继承图,我们至少应该能够知道,对于标准不可变序列类型Sequence,应该至少实现以下几种方法(遵循这些协议):
__contains__,__iter__,__len__,__reversed__,__getitem__,index,count
以Python的内置类型list为例说明这几个方法:
- 实现了
__contains__方法,就意味着list可以进行成员运算,即使用in和not in; - 实现了
__iter__方法,意味着list是一个可迭代对象,可以进行for循环、拆包、生成器表达式等多种运算; - 实现了
__len__方法,意味着可以使用内置函数len()。同时,当判断一个list的布尔值时,如果list没有实现__bool__方法,也会尝试调用__len__方法; - 实现了
__reversed__方法,意味着可以实现反转操作; - 实现了
__getitem__方法,意味着可以进行索引和切片操作; - 实现了
index和count方法,则表示可以按条件取索引和统计频数。
标准的Sequence类型声明了上述方法,这意味着继承自Sequence的子类,其实例化产生的对象将是一个可迭代对象、可以使用for循环、拆包、生成器表达式、in、not in、索引、切片、翻转等等很多操作。这同时也表明,如果我们说一个对象是不可变序列时,暗示这个对象是一个可迭代对象、可以使用for循环、......。
而对于标准可变序列MutableSequence,我们发现,除了要实现不可变序列中几种方法之外,至少还需要实现如下几个方法(遵循这些协议):
__setitem__,__delitem__,insert,append,extend,pop,remove,__iadd__
以Python的内置类型list为例这几个方法:
- 实现了
__setitem__方法,就可以对列表中的元素进行修改,如代码a[0]=2就是在调用这个方法 - 实现了
__delitem__,pop,remove方法,就可以对列表中的元素进行删除,如代码del a[0]就是在调用__delitem__方法 - 实现了
insert,append,extend方法,就可以在序列中插入元素; - 实现了
__iadd__方法,列表就可以进行增量赋值。
这就是说,对于标准可变序列类型,除了执行不可变类型的查询操作之外,其子类的实例对象都可以执行增删改的操作。
鸭子类型
抽象基类Sequence和MutableSequence声明了对于一个序列类型应该实现那些方法,很显然,如果一个类直接继承自Sequence类,内部也重载了Sequence中的七个方法,那么显然这个类一定是序列类型了,MutableSequence的子类也是一样。确实如此,但是当我们查看列表list、字符序列str、元组tuple的继承链时,发现在其mro列表(Method Resolution Order, MRO代表了类继承的顺序)中并没有Sequence和MutableSequence类,也就是说,这些内置类型并没有直接继承自这两个抽象基类。
>>> list.__mro__
(<class 'list'>, <class 'object'>)
>>> tuple.__mro__
(<class 'tuple'>, <class 'object'>)
>>> str.__mro__
(<class 'str'>, <class 'object'>)
其实,Python中有一种被称为“鸭子类型”的编程风格。在这种风格下,我们并不太关注一个对象的类型是什么,它继承自那个类型,而是关注他能实现那些功能,定义了那些方法。正所谓如果一个东西看起来像鸭子,走起来像鸭子,叫起来像鸭子,那他就是鸭子。
在这种思想之下,如果一个类并不是直接继承自Sequence,但是内部却实现了__contains__,__iter__,__len__,__reversed__,__getitem__,index,count几个方法,我们就可以称之为不可变序列。甚至都不必这么严格,可能只需要实现__len__,__getitem__两个方法就可以称作是不可变序列类型。对于可变序列也同样如此。
序列的操作
序列的特点是由若干元素组成,元素的分布有顺序,因此根据这个特点,它们支持一些共性的操作。
通用操作
以下是所有序列类型均支持的操作:
| 运算 | 结果 | 备注 |
| x in s | 如果 s 中的某项等于 x 则结果为 True,否则为 False | |
| x not in s | 如果 s 中的某项等于 x 则结果为 False,否则为 True | |
| s + t | s 与 t 相拼接 | |
| s * n 或 n * s | 相当于 s 与自身进行 n 次拼接 | |
| s[i] | s 的第 i 项,起始为 0 | 切片操作 |
| s[i:j] | s 从 i 到 j 的切片 | |
| s[i:j:k] | s 从 i 到 j 步长为 k 的切片 | |
| len(s) | s 的长度 | |
| min(s) | s 的最小项 | |
| max(s) | s 的最大项 | |
| s.index(x[, i[, j]]) | x 在 s 中首次出现项的索引号 | count 方法 |
| s.count(x) | x 在 s 中出现的总次数 | index 方法 |
| for i in x:pass | 迭代 | |
| hash(x) | 对象的哈希值 | 仅不可变序列 |
| sorted(x) | 排序 | |
| all(x) 或者 any(x) | 全真或者有真检测 | |
| iter(x) | 生成迭代器 |
可变序列类型
以下是仅可变序列支持的操作:
| 运算 | 结果: |
| s[i] = x | 将 s 的第 i 项替换为 x |
| s[i:j] = t | 将 s 从 i 到 j 的切片替换为可迭代对象 t 的内容 |
| del s[i:j] | 等同于 s[i:j] = [] |
| s[i:j:k] = t | 将 s[i:j:k] 的元素替换为 t 的元素 |
| del s[i:j:k] | 从列表中移除 s[i:j:k] 的元素 |
| s.append(x) | 将 x 添加到序列的末尾 |
| s.clear() | 从 s 中移除所有项 (等同于 del s[:]) |
| s.copy() | 创建 s 的浅拷贝 (等同于 s[:]) |
| s.extend(t) 或 s += t | 用 t 的内容扩展 s |
| s *= n | 使用 s 的内容重复 n 次来对其进行更新 |
| s.insert(i, x) | 在由 i 给出的索引位置将 x 插入 s |
| s.pop() 或 s.pop(i) | 提取在 i 位置上的项,并将其从 s 中移除 |
| s.remove(x) | 删除 s 中第一个 s[i] 等于 x 的项目。 |
| s.reverse() | 就地将列表中的元素逆序。 |
相关文章:
Python序列类型
序列(Sequence)是有顺序的数据列,Python 有三种基本序列类型:list, tuple 和 range 对象,序列(Sequence)是有顺序的数据列,二进制数据(bytes) 和 文本字符串&…...
【python爬虫】5.爬虫实操(歌词爬取)
文章目录 前言项目:寻找周杰伦分析过程代码实现重新分析过程什么是NetworkNetwork怎么用什么是XHR?XHR怎么请求?json是什么?json数据如何解析?实操:完成代码实现 一个总结一个复习 前言 这关让我们一起来寻…...
浅探Android 逆向前景趋势~
前段时间,我和朋友偶然间谈起安卓逆向,他问我安卓逆向具体是什么,能给我们带来什么实质性的东西,我也和朋友大概的说了一下,今天在这里拿出来和大家讨论讨论,也希望帮助大家来了解安卓逆向。 谈起安卓逆向…...
国际音标学习笔记
目录 1.单元音2.双元音3.辅音4.音节5.自然拼读法则5.1辅音字母的音标 1.单元音 我觉得单纯的音标并不好记住,所以就跟着老师整,根据单词记住音标的发音,以下是我的理解 音标对应的单词汉化iis衣əer饿ɔorigin奥u/ʊwoman五ʌart啊eanything哎…...
Azure - AzCopy学习
使用 AzCopy 将本地数据迁移到云存储空间 azcopy login 创建存储账号 ./azcopy login --tenant-id 40242385-c249-4746-95dc-4a0b64d49dc5这里的—tenant-id 在下面的地方查看:目录 ID;需要拥有Storage Blob Data Owner 的权限账号下可能会有很多目录&am…...
解决无法远程连接MySQL服务的问题
① 设置MySQL中root用户的权限: [rootnginx-dev etc]# mysql -uroot -pRoot123 mysql> use mysql; mysql> GRANT ALL PRIVILEGES ON *.* TO root% IDENTIFIED BY Root123 WITH GRANT OPTION; mysql> select host,user,authentication_string from user; -…...
mybatiplus代码生成器
目录 1.pom文件引入 2.引入模板引擎 3.注意 新版本,老版本配置和用法都不太一样,此处暂不展示;另外也可以尝试一下MyBatis-Flex 总之mybatisplus有的或者收费的,它都有MyBatis-Flex 是什么 - MyBatis-Flex 官方网站 1.pom文件…...
leetcode分类刷题:哈希表(Hash Table)(三、循环存在问题)
1、当需要快速判断某元素是否出现在序列中时,就要用到哈希表了。 2、本文针对的总结题型为给定的序列或需要构造的序列中是否存在循环,与 160. 相交链表、 141. 环形链表、142. 环形链表 II的题型一样。 202. 快乐数 这道题还考察如何对正整数求解各个位…...
43、基于 springboot 自动配置的 spring mvc 错误处理,就是演示项目报错后,跳转到自定义的错误页面
Spring MVC 的错误处理:基于 SpringBoot 自动配置之后的 Spring MVC 错误处理。 就是访问方法时出错,然后弄个自定义的错误页面进行显示。 ★ 两种错误处理方式 方式一: 基于Spring Boot自动配置的错误处理方式,只要通过属性文件…...
干货分享,现代列式数据库系统如何设计与实现? | StoneData 论文选读
作者:袁洋 | StoneData 技术架构师 审核:王博 论文链接:columnstoresfntdbs.pdf (harvard.edu) 列存四先驱和 MIT 知名教授 Samuel Madden 于 2013 年在某期刊上写的一篇当时列存相关技术的综述。文章还挺全面也很经典,通过剖析三…...
说说构建流批一体准实时数仓
分析&回答 基于 Hive 的离线数仓往往是企业大数据生产系统中不可缺少的一环。Hive 数仓有很高的成熟度和稳定性,但由于它是离线的,延时很大。在一些对延时要求比较高的场景,需要另外搭建基于 Flink 的实时数仓,将链路延时降低…...
北京筑龙受邀出席中物联“采购供应链中国行—走进雄安”活动
日前,“采购供应链中国行—走进雄安”活动在河北雄安新区成功举办,来自30家相关单位的50余名领导和代表参加了本次活动。活动由中国物流与采购联合会公共采购分会主办,中国物流与采购联合会采购委、中国雄安集团有限公司、河北雄安新区招标投…...
【Tkinter界面:练习-01】窗口-部件-布局
一、说明 python在用户界面开发中,其中有QT5,和Tkinter;对于实际项目,界面需要高大上,因此用QT5,对于开发人员的演示程序,或简单程序中,不建议QT5;用Tkinter已经足够。本…...
LeetCode每日一题:823. 带因子的二叉树(2023.8.29 C++)
目录 823. 带因子的二叉树 题目描述: 实现代码与解析: dp hash 原理思路: 823. 带因子的二叉树 题目描述: 给出一个含有不重复整数元素的数组 arr ,每个整数 arr[i] 均大于 1。 用这些整数来构建二叉树&#x…...
【教学类-35-01】学号+姓名+班级(描字帖)A4一页
背景说明: 本学期我带机动班,其中大4班去的频率比较高,与是我用大四班的名单做了一份 “描字帖”,在9月1日第一天见面时,孩子们用记号笔描字帖时,我也可以对这些孩子初步混个眼熟(聪明的&#x…...
UE5 里的一些常用的了解
# ACharacter、APawn的继承关系 ACharacter -继承自-> APawn -继承自-> AActor和 INavAgentInterface AActor -继承自-> UObject -继承自->UObjectBaseUtility -继承自-> UObjectBase(一个独立的类)INavAgentInterface是一个独立的类 #…...
【网络安全带你练爬虫-100练】第19练:使用python打开exe文件
目录 一、目标1:调用exe文件 二、目标2:调用exe打开文件 一、目标1:调用exe文件 1、subprocess 模块允许在 Python 中启动一个新的进程,并与其进行交互 2、subprocess.run() 函数来启动exe文件 3、subprocess.run(["文件路…...
【2D/3D RRT* 算法】使用快速探索随机树进行最佳路径规划(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
用反射实现自定义Java对象转化为json工具类
传入一个object类型的对象获取该对象的class类getFields方法获取该类的所有属性对属性进行遍历,并且拼接成Json格式的字符串,注意:通过属性名来推断方法名获取Method实例通过invoke方法调用 public static String objectToJsonUtil(Object o…...
rk3568 nvme硬盘分区,格式化,挂载测试
前言 环境介绍: 1.编译环境 Ubuntu 18.04.5 LTS 2.SDK rk356x_linux 3.单板 迅为itop-3568开发板 自制底板 一、查看硬盘 插上硬盘上电,进入系统后通过命令lspci查看nvme硬盘识别情况 [rootRK356X:/]# lspci -k 21:00.0 Class 0108: 1e4b:1202…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
