Fluent Python 2数据结构 1序列

目录

一、序列

2.1 列表推导和生成器表达式

2.1.1 列表推导

2.1.2 生成器表达式

2.2 元组

2.2.1 元组

2.2.2 元组拆包

2.2.3 collections.namedtuple

2.3 切片

2.3.1 为什么切片、区间会忽略最后一个元素

2.3.2 命名切片 slice(start, stop, step)

2.3.3 切片赋值

2.4 序列的 + 和 * 操作

2.5 list.sort 方法和内置函数 sorted

2.6 用 bisect 管理已排序的序列

2.7 替换列表的数据类型

2.7.1数组 array.array

2.7.2 内存视图

2.7.3 第三方库 NumPy和SciPy

2.7.4 双向队列 collections.deque 类


 

列表、 元组、数组以及队列

2.1 列表推导和生成器表达式

2.1.1 列表推导

3.列表推导

2.用列表推导替代map()、filter()

列表推导在 python3 之前会有变量泄漏的问题,python3 以后没有了。

原因是列表推导、生成器表达式,以及同它们很相似的集合(set)推导和字典(dict)推导,在 Python 3 中都有了自己的局部作用域,就像函数似的。表达式内部的变量和赋值只在局部起作用。

表达式的上下文里的同名变量还可以被正常引用,局部变量并不会影响到它们。

示例:

>>> s = 'guoyunfei'

>>> l = [s.upper() for s in s]  #局部变量s不会影响表达式外的s
>>> l
['G', 'U', 'O', 'Y', 'U', 'N', 'F', 'E', 'I']

2.1.2 生成器表达式

Python生成器及创建数据通道

14 章会专门讲到生成器的工作原理。
 

2.2 元组

2.2.1 元组

有些 Python 入门教程把元组称为“不可变列表”,这是不合适的,因为没有体现出元组作为记录的功能。

如果把元组当作一些字段的集合,那么数量和位置信息就能体现出来了。

2.2.2 元组拆包

元组拆包可以应用到任何可迭代对象上,唯一的硬性要求是,被可迭代对象中的元素数量必须要跟接受这些元素的元组的空档数一致。

除非我们用 * 来表示忽略多余的元素,在“用 * 来处理 多余的元素”一节里,会有它的具体用法。在 Python 中,函数用 *args 来获取不确定数量的参数算是一种经典写法了。4.拆包运算符(*)(**)

在进行拆包的时候,不总是对元组里所有的数据都感兴趣,_ 占位 符能帮助处理这种情况。

2.2.3 collections.namedtuple

1.18 映射名称到序列元素

collections.namedtuple 是一个工厂函数,它可以用来构建一个带字段名的元组和一个有名字的类——这个带名字的类对调试程序有很大帮助。

用 namedtuple 构建的类的实例所消耗的内存跟元组是一样的,因为字段名都被存在对应的类里面。这个实例跟普通的对象实例比起来也要小一些,因为 Python 不会用 __dict__ 来存放这些实 例的属性。7.2 如何为创建大量实例节省内存


2.3 切片

在 Python 里,像列表(list)、元组(tuple)和字符串(str)这类序列类型都支持切片操作.

2.3.1 为什么切片、区间会忽略最后一个元素

像这样,range(3) 和   list[:3] 只有 stop这个位置信息时,可以一眼看出返回元素个数即为 stop=3.
 
像这样,range(1,3) 和 list[1:3] 有 start和 stop起止位置信息时,可以直接 stop-start=2 算出返回元素个数
 
可以利用任意一个下标来把序列分割成不重叠的两部分,像这样,list[:x] 和 l ist[x:] 

 

2.3.2 命名切片 slice(start, stop, step)

对 seq[start:stop:step] 进行求值的时候, Python 会调用 seq.__getitem__(slice(start, stop, step))。
 
slice(start, stop, step)   1.11 命名切片
 
 

2.3.3 切片赋值

 
>>> l
[0, 1, 2, 3, 4]

>>> l[1:3] = [10,20,30]
>>> l
[0, 10, 20, 30, 3, 4]

2.4 序列的 + 和 * 操作

+ 和 * 不会修改两个被操作的序列,而是构建一个全新的序列作为拼接结果。

示例:

>>> l
[0, 10, 20, 30, 3, 4]
 
>>> l1 = l + [1,2,3]
>>> l1
[0, 10, 20, 30, 3, 4, 1, 2, 3]

>>> l2 = l * 3
>>> l2
[0, 10, 20, 30, 3, 4, 0, 10, 20, 30, 3, 4, 0, 10, 20, 30, 3, 4]

注意对复合对象(序列中元素是其他可变对象)使用 * 操作,是对原本元素的浅层复制 Python的浅层和深层复制

演示:

>>> l = [0,1,[3,4,5]]
>>> ln = l * 2
>>> ln
[0, 1, [3, 4, 5], 0, 1, [3, 4, 5]]
>>> ln[2][0] = 3000
>>> ln
[0, 1, [3000, 4, 5], 0, 1, [3000, 4, 5]]

 

2.5 list.sort 方法和内置函数 sorted

 
list.sort 方法会就地排序列表,不会把原列表复制一份。这也是这个方法的返回值是 None 的原因,提醒你本方法不会新建一个列 表。
在这种情况下返回 None 其实是 Python 的一个惯例:如果一个函数 或者方法对对象进行的是就地改动,那它就应该返回 None,好让调用 者知道传入的参数发生了变动,而且并未产生新的对象。
 
示例:
>>> l = l[2]
>>> l
[3000, 4, 5]
>>> l.sort()
>>> l
[4, 5, 3000]

sorted 则会新建一个列表作为返回值。sorted 可以接受任何形式的可迭代对象作为参数,包括不可变序列或生成器,最后都会返回一个列表。

示例:

>>> s = (5,2,-400)
>>> sorted(s)
[-400, 2, 5]

>>> g = (i for i in [200,10,99])
>>> sorted(g)
[10, 99, 200]

 

list.sort(*, key=None, reverse=False)

sorted(iterable, *, key=None, reverse=False)

可见,list.sort 和 sorted 都有 key 和 reverse 这两个关键字参数。

reverse 关键字参数的默认值是 False,如果被设定为 True,被排序的序列里的元素会以降序输出

key 关键字参数是一个只有一个参数的函数名,这个函数会被用在序列里的每一个元素上,所产生的结果将是排序算法依赖的对比关键字。

比如 key = len ,示例:

>>> sl = ['gyf','dz','kg','yyyy']
>>> sorted(sl,key=len)
['dz', 'kg', 'gyf', 'yyyy']

2.6 用 bisect 管理已排序的序列

bisect 模块包含两个主要函数, bisect insort ,两个函数都利用二分查找算法来在有序序列中查找或插入元素。
 
 

2.7 替换列表的数据类型

 

2.7.1数组 array.array

 
如果需要一个只包含数字的列表,那么 array.array 比 list 更高效。
 
class  array. array( typecode[,  initializer])
 
Python 数组跟 C 语言数组一样精简。创建数组需要一个类型码,这个类型码用来表示在底层的 C 语言应该存放怎样的数据类型。比如 b 类型码代表的是有符号的字符(signed char),因此 array('b') 创建出的 数组就只能存放一个字节大小的整数,范围从 -128 到 127,这样在序列很大的时候,我们能节省很多空间。而且 Python 不会允许你在数组里存放除指定类型之外的数据。
 
数组支持所有跟可变序列有关的操作,包括 .pop、.insert 和 .extend。另外,数组还提供从文件读取和存入文件的更快的方法,如 .frombytes 和 .tofile。
 

2.7.2 内存视图

 
memoryview 是一个内置类,它能让用户在不复制内容的情况下操作同一个数组的不同切片。
 
 

2.7.3 第三方库 NumPySciPy

 

2.7.4 双向队列 collections.deque

 
利用 .append 和 .pop 方法,我们可以把列表当作栈或者队列来用(比如,把 .append 和 .pop(0) 合起来用,就能模拟栈的“先进先出”的特点)。但是删除列表的第一个元素(抑或是在第一个元素之前添加一个元素)之类的操作是很耗时的,因为这些操作会牵扯到移动列表里的所有元素。
 
collections.deque 类(双向队列)是一个线程安全、可以快速从两端添加或者删除元素的数据类型。而且如果想要有一种数据类型来存放“最近用到的几个元素”,deque 也是一个很好的选择。这是因为在新建一个双向队列的时候,你可以指定这个队列的大小,如果这个队列满员了,还可以从反向端删除过期的元素,然后在尾端添加新的元素。示例 2-23 中有几个双向队列的典型操作
 
 
除了 deque 之外,还有些其他的 Python 标准库也有对队列的实现。

queue,multiprocessing 是设计给进程间通信

asyncio 为异步编程里的任务 管理提供了专门的便利。

heapq 可以把可变序列当作堆队列或者优 先队列来使用。 Python heapq 堆排序算法
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值