第二部分 数据结构

第2章 序列构成的数组

内置序列类型
序列类型 序列 特点
容器序列 list、tuple、collections.deque - 能存放不同类型的数据;
- 存放的是任意类型的对象的引用
扁平序列 str、bytes、bytearray、memoryview、array.array - 只能容纳一种类型;
- 存放的是数据值;
- 是一段连续的内存空间;
- 只能存放字符、字节、数值等基础类型
可变序列与不可变序列

可变序列:list、bytearray、array.array、collections.deque、memoryview

不可变序列:tuple、str、bytes

当改变了不可变序列的内容时,不可变序列的引用也会发生改变(对于str的修改,实质上是添加一个新的str对象,并将该对象的引用传回原实例),故效率低。他们的区别包括:

  • 函数参数传递

    1. def funForList(l):
    2. l.append(4) #[1, 2, 3] => [1, 2, 3, 4]
    3. def funForStr(str):
    4. str = str.lower() #"ABC" => "abc"
    5. t_list = [1, 2, 3]
    6. funForList(t_list)
    7. print(t_list) #[1, 2, 3, 4] 可变序列经过函数改变后本身发生了改变
    8. t_str = "ABC"
    9. funForStr(t_str)
    10. print(t_str) #"ABC" 不可变序列经过函数改变后本身并不会发生了改变
  • 对象之间的传递

  1. list_1 = []
  2. list_2 = list_1
  3. list_2.append(1)
  4. print(list_1) #list_1 原本的空序列也发生了改变
  5. str_1 = ""
  6. str_2 = str_1
  7. str_2 = "abc"
  8. print(str_1) #str_1 没有发生改变

具体相关可以通过http://pythontutor.com/的可视化分析工具查看内部的运行流程

列表推导式

语法

[ 输出表达式 循环1 循环2 .... 过滤表达式]

  1. # 获取20以内的3的倍数
  2. list_1 = [x for x in range(1, 20) if not x%3]
  3. print(list_1) #[0, 3, 6, 9, 12, 15, 18]
特点

不会有变量泄露的问题,列表推导和生成器表达式,以及集合推导、字典推导等,在Python3里都有了自己的局部作用域。

生成表达式

特点

生成器表达式背后遵守了迭代器协议,可以逐个产出元素,而不是先建立一个完整的表,然后再把这个列表传递到某个构造函数里。前面的方式更能节省内存。

元组

* 运算符
  1. 拆分可迭代对象

    1. def numberAdd(a,b):
    2. return a+b
    3. print(numberAdd(*(1,2))) #将元组(1,2)拆成1,2两个单独的元素对象作为参数
    4. # 3
  2. 元素拆包用 * 处理剩下的元素,以 * 为前缀的对象可以出现在赋值表达式的任意位置

    1. a, *b, c = range(5) #a=0 b=[1, 2, 3] c=4
具名元组

collections.namedtuple 是一个工厂函数,可以用来构建一个带字段名的元组和一个有名字的类

  1. Student = collections.namedtuple('Student','name age gender')
  2. stu = Student('Ming', 18, 'man')
  3. print(stu)
  4. # Student(name='Ming', age=18, gender='man')
多维切片和省略
  • 省略(...)是 Ellipsis 对象的别名,Ellipsis 对象是 ellipsis 类的单一实例。

  • 如果 x 是四维数组,x[i, ...] 就是 x[i, :, :, :] 的缩写

对序列使用 + 和 *
  • 不修改原有操作对象,而是构建一个全新的序列。

  • [[] *3] *4 不等于 [[] *3 for _ in range(4)] ,前者的元素的引用指向的是同一个值

    1. l1 = [[] *3] *4
    2. l1[0].append(1)
    3. print(l1)
    4. # [[1], [1], [1], [1]]序列
序列的增量赋值
  • a += b,就地相加,效率高

  • a = a+b,先计算 a+b,然后赋值,产生了新的对象,效率较低

  • 对不可变序列进行重复拼接操作,效率会很低(str 是一个意外,因为对字符串做 += 太普遍了,所以Cpython做了相应的优化)

  • 一个谜题

    1. t = (1, 2, [30, 40])
    2. t[2] += [50, 60]
    3. # a. t 变成(1, 2, [30, 40, 50, 60])
    4. # b. 因为tuple不支持对它的元素赋值,所以会抛出TypeError异常
    5. # c. 以上两个都不是
    6. # d. a 和 b都是对的
    7. # 正确答案 d
    • 三个教训

      • 不要把不可变对象放在元组里面
      • 增量赋值不是原子操作,虽然抛出异常,但还是可能完成操作
      • 查看Python的字节码对了解代码背后的运行机制很有帮助
bisect 二分查找
  • bisect_left(nums,target,left, right) #找到nums中第一个 大于等于 target的目标位置
  • bisect.insort_left(nums,target,left, right) #将target 插入到该位置(搜索是O(log n), 插入却是O(n))
  • bisect.bisct(nums,target,left,right) #找到nums中第一个 大于 target的目标位置
  • bisect.bisct_right(nums,target,left,right) #同bisct
  • bisect.insort(nums,target,left, right) #将target 插入到该位置(搜索是O(log n), 插入却是O(n))
  • bisect.insort_right(nums,target,left,right) #同bisct
数组 array
  • array.fromfile 从二进制文件读双精度浮点数,比从文本文件读取的速度快60倍
  • array.tofile 将浮点数写入二进制文件,比以每行一个浮点数的方式写入到文本文件快7倍
内存视图

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

双向队列
  • collections.deque 类是一个线程安全,可以快速从两端添加或者删除元素的数据类型
  • 添加或者删除元素的操作都是原子操作,可以在多线程中安全使用,不需要担心资源锁的问题
TimSort

Timsort 是 sorted 和 list.sort 背后的排序算法

第3章 字典和集合

collections.abc 模块
  • 该模块中含有 Mapping 和 MutableMapping 抽象基类
  1. my_dict = {}
  2. print(isintance(my_dict, abc.Mapping))
  3. # True
  • dict 映射要求映射的键是 可散列的数据类型(对象的内部状态都是不可变的,例如str,bytes,数值类型,元素全部为不可变类型的tuple)
字典推导
  1. my_dict = {key: value for key, value in list}
  • 当dict 中的键没有找到时:

    • d[k] 找不到该键时,Python会抛出异常

    • 用 d.get(k, default) 代替 d[k],找不到时返回默认值

    • setdefault

      1. mydict.setdefault(key, []).append(new_value)
      2. # 等同于下面,但只进行一次查询
      3. if key not in my_dict:
      4. my_dict[key] = []
      5. my_dict[key].append(new_value)
映射的弹性键查询
  • collections.defaultdict

    设置默认的函数作为default_dactory 创建一个defaultdict

  1. d = collections.defaultdict(lambda :None)
  2. print(d[0])
  3. # None
  4. d = collections.defaultdict(list)
  5. print(d[0])
  6. # []
  • 特殊方法 __ missing __

    当键没有找到时,系统将调用 __ missing __ 方法,可以自定义类继承 dict 并实现 __ missing __ 方法

字典的变种
  • collections.OrderedDict #添加键的时候保持顺序

  • collections.ChainMap #可以容纳不同的映射对象,键查找时,将在不同的映射对象中之一查找直到被找到

  • collections.Counter #给键准备计数器

    1. ct = collections.Counter("aabbcc")
    2. # Counter({'a':2, 'b':2, 'c':2})
    3. ct.update('aaazzz')
    4. # Counter({'a':5, 'z':3, 'b':2, 'c':2})
不可变映射类型

types.MappingProxyType

  • 给这个类添加映射,返回一个只读的映射视图,但当原映射视图有变动时,该视图也将变动,且不能直接在只读映射视图上做修改
  1. d = {1:'A'}
  2. d_proxy = types.MappingProxyType(d)
  3. print(d_proxy)
  4. # mappingproxy({1:'A'})
  5. d[2] = 'B'
  6. print(d_proxy)
  7. # mappingproxy({1:'A', 2:'B'})
  8. d_proxy[2] = 'C'
  9. # TypeError:..........
集合
运算符 方法 描述
s & z s. __ and __ (z) s 和 z 的交集
s | z s. __ or __ (z) s 和 z 的并集
s - z s. __ sub __ (z) s 和 z 的差集
s ^ z s. __ xor __ (z) s 和 z 的对称差集
e in s s. __ contains __ (e) s 是否包含元素 e
s <= z s. __ le __ (z) s 是否为 z 的子集
s < z s. __ lt __ (z) s 是否为 z 的真子集
s >= z s. __ ge __ (z) s 是否为 z 的父级
s > z s. __ gt __ (z) s 是否为 z 的真父级
dict 和 set 特点
  • dict 键或 set 元素必须是可散列的
  • 字典、集合在内存上的开销巨大
  • dict 键或 set 元素查询很快
  • dict 键或 set 元素的次序取决于添加顺序
  • 往dict 或 set 添加新键可能改变已有键的顺序

第4章 文本和字节序列

字符、字节
  • Python3 中采用 Unicode字符标准,以及 Utf-8 编码标准
  • bytes 或 bytearray 对象中各个元素是介于0~255之间的整数
  1. cafe = bytes('café',encoding='utf-8')
  2. print(cafe)
  3. # b'caf\xc3\xa9'
  4. print(cafe[0])
  5. # 99
  6. print(cafe[:1])
  7. # b'c'
  8. # cafe[0] 获取的是一个整数,而cafe[:1]返回的是一个长度为1的bytes对象
结构体和内存视图

struct模块能处理bytes,bytearray和memoryview对象。

编码

在文件顶部添加一个神奇的coding注释

  1. # coding: cp1252
解码

解码过程中可能出现三种错误

  • unicodedecodeerror(把二进制序列转化为字符串)
  • unicodeencodeerror(把字符串转化为二进制序列)
  • syntaxerror
处理文本文件
Unicode三明治
  • 尽早把输入的字节序列编码成字符串
  • 业务逻辑处理是,不能进行编码或解码
  • 尽量晚地把字符串编码成字节序列

《流畅的Python》第二部分 数据结构 【序列构成的数组】【字典和集合】【文本和字节序列】的更多相关文章

  1. Python算法与数据结构--求所有子数组的和的最大值

    Python算法与数据结构--求所有子数组的和的最大值 玄魂工作室-玄魂 玄魂工作室秘书 玄魂工作室 昨天 题目:输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个 ...

  2. Fluent_Python_Part2数据结构,04-text-byte,文本和字节序列

    文本和字节序列 人使用文本,计算机使用字节序列 1. 大纲: 字符.码位和字节表述 bytes.bytearray和memoryview等二进制序列的独特特性 全部Unicode和陈旧字符集的编解码器 ...

  3. 流畅的python第四章文本和字节序列学习记录

    字符问题 把码位转化成字节序列的过程是编码,把字节序列转化成码位的过程是解码 把unicode字符串当成人类可读的文本,码位当成机器可读的, 将字节序列编程人类可读是解码,把字符串编码成字节序列是编码 ...

  4. Python【第二课】 字符串,列表,字典,集合,文件操作

    本篇内容 字符串操作 列表,元组操作 字典操作 集合操作 文件操作 其他 1.字符串操作 1.1 字符串定义 特性:不可修改 字符串是 Python 中最常用的数据类型.我们可以使用引号('或&quo ...

  5. python高级(四)—— 文本和字节序列(编码问题)

    本文主要内容 字符 字节 结构体和内存视图 字符和字节之间的转换——编解码器 BOM鬼符  标准化Unicode字符串 Unicode文本排序 python高级——目录 文中代码均放在github上: ...

  6. Python笔记——基本数据结构:列表、元组及字典

    转载请注明出处:http://blog.csdn.net/wklken/archive/2011/04/10/6312888.aspx Python基本数据结构:列表,元组及字典 一.列表 一组有序项 ...

  7. Python 文本和字节序列

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Helvetica } Python 3 明确区分了人类可读的文本字符串和原始的字节序列.隐式 ...

  8. Python的文本和字节序列

    一.字符串的表示和存储 字符串是字符的序列,每个字符都有有一个数字作为标识,同时会有一个将标识转换为存储字节的编码方案: s = 'hello world python' for c in s: pr ...

  9. 小甲鱼Python第二十三讲课后习题--025,字典

    笔记: 1.字典是Python中唯一的映射类型 2.字典包含两个要素:键(key)和值(value)他们是成对出现的,用大括号括起来,多对存在时用逗号隔开. 3.可以用dict()直接创建字典,如di ...

随机推荐

  1. 【MySQL】我这样分析MySQL中的事务,面试官对我刮目相看!!

    写在前面 相信大部分小伙伴在面试过程中,只会针对面试官提出的表面问题来进行回答.其实不然,面试官问的每一个问题都是经过深思熟虑的,面试的时间相对来说也是短暂的,面试官不可能在很短的时间内就对你非常了解 ...

  2. 为什么选择H5游戏开发定制?

    为什么选择H5游戏开发定制? 随着微信H5游戏推广带来的显著效果,越来越多的商家已经加入到游戏营销的队伍中来, 对H5小游戏有了解的商家都知道,[模板游戏]的价格往往低于[定制游戏]的价格,可是为什么 ...

  3. 第一次编程作业(My Own Score)

    博客班级 https://edu.cnblogs.com/campus/fzzcxy/2018SE2 作业要求 https://edu.cnblogs.com/campus/fzzcxy/2018SE ...

  4. jni之jni与jna的比较

    java开发过程中会遇到需要调用c/c++动态库(windows平台的dll和linux平台的so)的情况,可以使用JNI或者JNA技术. JNA基于JNI技术开发,主要在上层作了类型自动转换的封装, ...

  5. RocketMQ的发送模式和消费模式

    前言 小伙伴们大家好啊,王子又来和大家一起闲谈MQ技术了. 通过之前文章的学习,我们已经对RocketMQ的基本架构有了初步的了解,那今天王子就和大家一起来点实际的,用代码和大家一起看看RocketM ...

  6. d3力导图绘制节点间多条关系平行线的方法

    之前用d3做了多条线之间的绘图是曲线表示的,现在产品要求改成平行线的样式,经过在网上的调研和自己的尝试,实践出一个可用的方法,分享给大家,先展示下结果: 事先声明,本方法是在以下参考网站上进行的结合和 ...

  7. linux6.4内核由2.6升级成3.6

    安装CentOS 6.4之后,内核默认是2.6.32.由于docker需要3.0以上的内核,所以需要对内核进行升级. 1. 安装必要组件# yum -y install ncurses-devel # ...

  8. Apache和分布式部署

    1.tomcat分布式部署 1.1.要配置几个tomcat,就部署几个相同程序名的tomcat 1.2.配置每个tomcat下server.xml中ajp端口,以及后面的jvmRoute,第几个就配置 ...

  9. oracle之三备份恢复概述

    备份恢复概述 1.1 数据库故障的类型: 1)user process failure: pmon 自动处理 2)instance failure: smon 自动处理 3)user errors : ...

  10. JVM运行时数据区--堆

    一个进程对应一个jvm实例,一个运行时数据区,又包含多个线程,这些线程共享了方法区和堆,每个线程包含了程序计数器.本地方法栈和虚拟机栈. 核心概述 1.一个jvm实例只存在一个堆内存,堆也是java内 ...