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']],这是一个列表。

 

可以看到,对于列表本身来说,其在内存中是连续的,但是列表的内存中存储的并不是值本身,而是对象(列表中元素)的引用。至于对象(列表中的元素)本身,则存储在别的内存块中,这些内存可能是连续的,也可能是不连续的,大概率是不连续的。而且,列表中不仅仅可以存储基本数据类型intstr,还可以存储列表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中,与其他常见的类如intlist等不同,这两个基类都是抽象基类,抽象基类确定了序列类型的协议,所有属于序列类型的都要遵循这个抽象基类的协议。

Sequence和MutableSequence两个类的继承关系如下:

 

可变序列MutableSequence类继承自不可变序列Sequence类,Sequence类又继承了两个类Reversible和Collection,Collection又继承自Container、Iterable、Sized三个抽象基类。通过这个继承图,我们至少应该能够知道,对于标准不可变序列类型Sequence,应该至少实现以下几种方法(遵循这些协议):

__contains__,__iter__,__len__,__reversed__,__getitem__,index,count

 以Python的内置类型list为例说明这几个方法:

  • 实现了__contains__方法,就意味着list可以进行成员运算,即使用innot in
  • 实现了__iter__方法,意味着list是一个可迭代对象,可以进行for循环、拆包、生成器表达式等多种运算;
  • 实现了__len__方法,意味着可以使用内置函数len()。同时,当判断一个list的布尔值时,如果list没有实现__bool__方法,也会尝试调用__len__方法;
  • 实现了__reversed__方法,意味着可以实现反转操作;
  • 实现了__getitem__方法,意味着可以进行索引和切片操作;
  • 实现了indexcount方法,则表示可以按条件取索引和统计频数。

标准的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

与 t 相拼接

s * n 或 n * s

相当于 s 与自身进行 n 次拼接

s[i]

的第 i 项,起始为 0

切片操作

s[i:j]

从 i 到 j 的切片

s[i:j:k]

从 i 到 j 步长为 k 的切片

len(s)

的长度

min(s)

的最小项

max(s)

的最大项

s.index(x[, i[, j]])

在 s 中首次出现项的索引号
(索引号在 i 或其后且在 j 之前)

count 方法

s.count(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[len(s):len(s)] = [x])

s.clear()

从 s 中移除所有项 (等同于 del s[:])

s.copy()

创建 s 的浅拷贝 (等同于 s[:])

s.extend(t) 或 s += t

用 t 的内容扩展 s
(基本上等同于 s[len(s):len(s)] = t)

s *= n

使用 s 的内容重复 n 次来对其进行更新

s.insert(i, x)

在由 i 给出的索引位置将 x 插入 s
(等同于 s[i:i] = [x])

s.pop() 或 s.pop(i)

提取在 i 位置上的项,并将其从 s 中移除

s.remove(x)

删除 s 中第一个 s[i] 等于 x 的项目。

s.reverse()

就地将列表中的元素逆序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/108990.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据生成 | MATLAB实现GAN生成对抗网络结合SVM支持向量机的数据生成

数据生成 | MATLAB实现GAN生成对抗网络结合SVM支持向量机的数据生成 目录 数据生成 | MATLAB实现GAN生成对抗网络结合SVM支持向量机的数据生成生成效果基本描述程序设计参考资料 生成效果 基本描述 数据生成 | MATLAB实现GAN生成对抗网络结合SVM支持向量机的数据生成。 生成对抗…

UnitTest笔记: 拓展库DDT的使用

DDT (Data-Drivers- Tests) 允许使用不同的测试数据运行同一个测试用例&#xff0c;展示为不同的测试用例。 第一步&#xff1a; pip安装 ddt 第二步&#xff1a; 创建test_baidu_ddt.py 1. 测试类要使用ddt 修饰 2. 不同形式的参数化&#xff1a; 列表&#xff0c;字典&a…

Mesa 23.2 开源图形栈现已可供下载

作为 Mesa 23 系列的第二个重要版本&#xff0c;Mesa 23.2 开源图形栈现已可供下载&#xff0c;它为 AMD GPU 的 RADV Vulkan 驱动程序带来了新功能&#xff0c;改进了 Linux 游戏&#xff0c;并新增了 Asahi 功能。 Mesa 23.2 的亮点包括 Asahi 上的 OpenGL 3.1 和 OpenGL ES …

Windows用户如何安装Cpolar

目录 概述 什么是cpolar&#xff1f; cpolar可以用在哪些场景&#xff1f; 1. 注册cpolar帐号 1.1 访问官网站点 2. 下载Windows版本cpolar客户端 2.1 下载并安装 2.2 安装完验证 3. token认证 3.1 将token值保存到默认的配置文件中 3.2 创建一个随机url隧道&#x…

java八股文面试[JVM]——JVM调优

知识来源&#xff1a; 【2023年面试】JVM性能调优实战_哔哩哔哩_bilibili

java gradle 项目 在idea上 搭建一个简单的thrift实例

前言 Thrift是RPC通信的一种方式&#xff0c;可以通过跨语言进行通信&#xff0c;最近项目需要进行跨语言的通信&#xff0c;因此首先尝试搭建了一个简单的thrift框架&#xff0c;因为网上的实例大都参差不全&#xff0c;通过gpt查询得到的结果对我帮助更大一点&#xff0c;但…

爱奇艺数据湖实战 - 基于数据湖的日志平台架构演进

01 背景 为了满足公司内日志实时查询分析的需求&#xff0c;爱奇艺大数据团队自研了Venus日志服务平台&#xff0c;负责爱奇艺各服务日志的采集、存储、处理、分析等场景。早期采用基于ElasticSearch的存储分析架构&#xff0c;随着数据规模的不断扩大&#xff0c;出现了成本高…

大数据-玩转数据-Flink窗口函数

一、Flink窗口函数 前面指定了窗口的分配器, 接着我们需要来指定如何计算, 这事由window function来负责. 一旦窗口关闭, window function 去计算处理窗口中的每个元素. window function 可以是ReduceFunction,AggregateFunction,or ProcessWindowFunction中的任意一种. Reduc…

mysql 命令行 执行sql文件

方法1 source source file.sql; file.sql : 绝对路径或 相对路径。 方法2 mysql -u xxx -p < file.sql 方法3 MySQLImport 工具 mysqlimport [options] database file_name 其中&#xff0c;database为要导入数据的数据库名&#xff0c;file_name为要导入的SQL文件名。还可以…

算法通过村第四关-栈白银笔记|括号问题

文章目录 前言1. 括号匹配问题2. 最小栈问题3. 最大栈 总结 前言 提示&#xff1a;如果让我送给年轻人四个字&#xff0c;就是&#xff1a;量力而行。 量力而行不会失眠&#xff0c;不会啃老&#xff0c;不会为各种考试焦虑。顺其自然活得轻松。其实&#xff0c;量力而行最易大…

Docker学习笔记

Docker学习笔记 docker的作用docker的基本组成安装docker阿里云镜像加速run的流程和docker原理 docker的思想来自于集装箱。 核心思想&#xff1a; 隔离 docker可以通过隔离机制将服务器利用到极致。 虚拟机&#xff1a;在windows中装一个Vmware&#xff0c;通过这个软件可以虚…

使用EF Core更新与修改生产数据库

使用EF Core的Code First&#xff0c;在设计阶段&#xff0c;直接使用Database.EnsureCreated()和EnsureDeleted()可以快速删除、更新最新的数据结构。由于没有什么数据&#xff0c;删除的风险非常低。但是对于已经投入生产的数据库&#xff0c;这个方法就绝对不可行了。 考虑…

粒子群算法的基本原理和Matlab实现

1.案例背景 1.1 PSO算法介绍 粒子群优化算法(Particle Swarm Optimization,PSO)是计算智能领域,除了蚁群算法,鱼群算法之外的一种群体智能的优化算法,该算法最早是由Kennedy和 Eberhart 在1995年提出的。PSO算法源于对鸟类捕食行为的研究,鸟类捕食时,每只鸟找到食物最简单有效…

mac清理磁盘空间软件有哪些 mac清理磁盘空间怎么清理

随着时间的推移&#xff0c;Mac电脑上的文件会越来越多&#xff0c;很快就会占满磁盘空间。这时候&#xff0c;我们需要一个好的Mac清理磁盘空间软件来释放空间&#xff0c;保持电脑的良好性能。那么&#xff0c;mac清理磁盘空间软件有哪些呢&#xff1f;接下来&#xff0c;我将…

用 PHP 和 JavaScript 显示地球卫星照片

向日葵 8 号气象卫星是日本宇宙航空研究开发机构设计制造的向日葵系列卫星之一&#xff0c;重约 3500 公斤&#xff0c;设计寿命 15 年以上。该卫星于 2014 年 10 月 7 日由 H2A 火箭搭载发射成功&#xff0c;主要用于监测暴雨云团、台风动向以及持续喷发活动的火山等防灾领域。…

几个nlp的小任务(生成式任务——语言模型(CLM与MLM))

@TOC 本章节需要用到的类库 微调任意Transformers模型(CLM因果语言模型、MLM遮蔽语言模型) CLM MLM 准备数据集 展示几个数据的结构

【Spring Boot】数据库持久层框架MyBatis — MyBatis简介

MyBatis简介 本节首先会介绍什么是ORM、什么是MyBatis、MyBatis的特点以及核心概念&#xff0c;最后介绍MyBatis是如何启动、如何加载配置文件的&#xff1f; 1.什么是ORM ORM&#xff08;Object Relational Mapping&#xff0c;对象关系映射&#xff09;是为了解决面向对象…

下一代存储解决方案:湖仓一体

文章首发地址 湖仓一体是将数据湖和数据仓库相结合的一种数据架构&#xff0c;它可以同时满足大数据存储和传统数据仓库的需求。具体来说&#xff0c;湖仓一体可以实现以下几个方面的功能&#xff1a; 数据集成&#xff1a; 湖仓一体可以集成多个数据源&#xff0c;包括结构…

C++ 网络编程项目fastDFS分布式文件系统(九)总结

1. Location语法 1. 语法规则 location [ |~|~ * |^~ ] /uri/ { … } 正则表达式中的特殊字符 : - . () {} [] * ? 2. Location 优先级说明 在 nginx 的 location 和配置中 location 的顺序没有太大关系。 与 location 表达式的类型有关。 相同类型的表达式&a…

K8S最新版本集群部署(v1.28) + 容器引擎Docker部署(上)

温故知新 &#x1f4da;第一章 前言&#x1f4d7;背景&#x1f4d7;目的&#x1f4d7;总体方向 &#x1f4da;第二章 基本环境信息&#x1f4d7;机器信息&#x1f4d7;软件信息&#x1f4d7;部署用户kubernetes &#x1f4da;第三章 Kubernetes各组件部署&#x1f4d7;安装kube…