摘要
- Python语言,底层使用了C实现了丰富的序列类型,这些序列类型按照不同的特性,可以分为:容器序列和扁平序列、可变序列和不可变序列。
- 这些序列还实现了丰富的内置方法,把例如排序的一些基本操作封装好,用户只要简单调用就可以了,当然个别geek讲究一个效率,会自己编写更加符合具体业务场景的方法。
- 列表推导式、生成器表达式、元组、切片、关于元组的可变与不可变的问题及其本质。
一、序列类型
1. 容器序列和扁平序列
(1)容器序列:可容纳不同数据类型的元素
- list
- tuple
- deque : collections中调用
(2)扁平序列:只能容乃一种数据类型的元素
- bytes
- str
- bytearray
- memaryvies : 内存视图,在处理大数据的时候回用到,很有意思的一个序列,有一个个博主讲解的很好,附上链接 《 python memoryview内存视图》
2. 可变序列和不可变序列
理解和区可变不可变序列首先要明确,可变和不可变的概念,变的是什么,不变的是什么,我是这么理解的:
- 当序列被创建,并且添加完元素之后,能否动态修改元素,动态修改元素,比如插入、更新、删除某个元素
- 如果可以动态修改元素,则可以说这个序列是可变的
- 反之,不能动态修改元素,则说明这个元素是不可变的
(1)可变序列:元素可以动态修改(部分容器序列)
例如 list dict都是可变序列
(2)不可变序列:元素不可动态修改
a. 比较经典的不可变序列就不得不说tuple(元组),关于元组和不可变序列有个比较经典的问题:
问:为什么可以改变元组内部的元素值?不是说元组是不可变序列类型吗?
答:首先明确一个Python中的概念,就是一切皆对象,很像Linux中的一切皆文件对吧。元组t1中保存的知识元素的引用,元组的不可变性其实是一种相对不可变性
元组与多数Python集合一样,保存的是对象的引用,如果保存的引用的元素是可变的,即使元组本事不可变,元素依然可变。也就是说,元素的不可变性其实是指tuple数据结构的物理内容不可变,与引用本身无关。
关于元组的迷之操作还有一个,题目描述和选项如下:
思考一下这道题的选项,
这是一种非常罕见的边界现象;
首先,元组作为一种不可变序列,是不能被赋值的,所以b是正确的;
其次,序列自增不是原子操作,所以可以看到,元组中的可变序列最终还是完成了自增操作操作。
正确答案:d
因此在使用元组序列存储元素的时候要注意:
1. 元组中不要放可变序列
2. 序列自增操作不是原子操作
b.具名元组
具名元组的导入 form collections import nametuple
具名元组是一个函数工厂,可以穿件一个带字段的tuple和一个有名字的类,没有方法。占用的内存却和元组想同。附上笔记:
二、列表推导式和生成器表达式
1. 列表推导式
a = [i for i in range(10)]
2. 生成器表达式
b = (i for i in range(10))
找不同~
3. Tips
- 列表推导式的唯一作用是生成一个list,其他的序列类型用生成器表达式
- 列表推导式是先创建一个list,然后创建元素,而成成器表达式遵循迭代协议,可以逐个产生元素,更节省空间,也就是说,生成器只有你调用的时候才给你生成元素。
- 生成器表达式返回的是一个generotor对象,不能直接调用,要不用next方法,要不放在迭代表达式中逐个获取元素
- 如下:
b = (i for i in range(10))
for i in b:
print(i)