chapter 2.1

  • 字符串与字节序列
  • 字符串编码为字节序列
  • 字节序列转换为字符串
  • 字节数组bytearray
  • 字符串的拼接
  • list实现细节
  • 列表推导
  • zip
  • 序列解包
  • 字典
  • 集合

字符串与字节序列

(str,bytes)

  • Python3中只有一种能够保存文本信息的数据类型,就是str(string,字符串,不可变序列)
  • Python2中用str来表示字节字符串
  • Python3中用bytes对象来处理字节字序列(字节字符串,不可变序列)
  • Python3所有被'"'''包裹且没有前缀的值都表示str数据类型,都是Unicode.
  • Python2中,Unicode需要加u’xxx’前缀,Python3向后兼容,仍支持这个前缀
  • Unicode字符串中包含无法用字节表示的抽象文本.Unicode字符串需要被编码为二进制数据,才能在磁盘中保存或在网络中传输

bytes(0~255)之间的整数

print(bytes([100,101,102,103,104]))
b'defgh'

bytes或者bytearray,转化为其他序列类型(list/tuple),也会显示真面目.

list(b'defgh')
[100, 101, 102, 103, 104]
tuple(b'defgh')
(100, 101, 102, 103, 104)
set(b'defgh')
{100, 101, 102, 103, 104}
u'今晚打老虎'
'今晚打老虎'

字符串编码为字节序列

  • str.encode(encoding, errors),encoding默认’utf-8’
  • bytes(source, encoding, errors),source:字符串,encoding:指定编码格式,没有默认参数

字节序列转换为字符串

  • bytes.decode(encoding, errors)

  • str(source, encoding, errors),source:字节序列

字节数组bytearray

bytes和str都是不可变对象(每一次微小的修改,都会创建一个新的实例),bytearray是bytes的可变版本,可以任意修改,可以像操作列表一样(append, pop, insert)

字符串的拼接

str在python中作为一个不可变的对象,任意拼接两个字符串都会创建一个新的字符串对象.

如果用循环来拼接多个字符串:

s = ''
for string in str_list:s += string

因为str为不可变的,通过循环拼接多个str是一种效率极低的方法.str.join()是一种快速的方法.

s = ''.join(str_list)

str.join()方法的注意事项:

  • .join()方法虽然很快,但是并不意味着所有的拼接操作都要用到它,仅在拼接很多个字符串时是最佳选择
  • 代码的可读性,可读性是最重要的,拼接较少字符串时’+'更合适
  • Cpython中的constant folding,一些复杂的字面值(较长的字符串)会被转换为更短的形式,例如:'a'+'b'+'c'转换为'abc'

Python : list实现细节

  实际上在CPython中列表是由长度可变的数组实现的.Python中的列表是由对其他对象的引用组成的连续数组.指向这个数组的指针及其长度被保存在一个列表的头部结构中,在python中创建列表时,也就是CPython中创建变长数组时,采用了(exponential over-allocation),所以每次插入或删除某个元素并不会改变数组的大小.

列表操作的平均时间复杂度:

  • 复制 :O(n)
  • 添加元素 :O(1)
  • 插入元素 :O(n)
  • 获取元素 :O(1)
  • 修改元素 :O(1)
  • 删除元素 :O(n)
  • 遍历 :O(n)
  • 获取长度为k的片段 :O(k)
  • 删除片段 :O(n)
  • 修改长度为k的片段 :O(n+k)
  • 列表扩展extend :O(k)
  • 乘以k :O(n*k)
  • 测试元素是否在列表中 :O(n)
  • min()/max() :O(n)
  • 获取列表的长度 :O(1)

列表推导

evens = []
for i in range(100):if i % 2 ==0:evens.append(i)

在python写这样的代码是很糟糕的,原因如下:

  • 解释器在每次循环中都需要判断列表中的哪一部分需要修改
  • 需要一个计数器来跟踪需要处理的元素
  • append()是一个列表方法,每次便利时需要额外执行一次查询函数
evens = [i for in range(100) if i % 2 == 0]
列表推导和内部数组大小的调整

解释器在对列表推导进行求值过程中并不知道最终容器的大小,因此它是无法为数组预先分配大小的.

zip

zip可对多个长度相等的可迭代对象进行均匀的遍历:

for item in zip([1,2,3],[4,5,6],[7,8,9]):print(item)
>>>(1, 4, 7)
>>>(2, 5, 8)
>>>(3, 6, 9)

对zip()函数返回的结果再次调用zip():

for item in zip(*zip([1,2,3],[4,5,6],[7,8,9])):print(item)
>>>(1, 2, 3)
>>>(4, 5, 6)
>>>(7, 8, 9)

Sequence Unpacking序列解包

不局限于列表和元组,是用于任意序列类型(字符串.字节序列)

a, b, c = 1, 2, 3
print(a, b, c)
>>>1 2 3a, b, c = 'edc'
print(a, b, c)
>>>e d ca, b, c = b'edc'
print(a, b, c)
>>>101 100 99

解包还可以利用*表达式获取单个变量中的多个元素:

a, b, *c = 'abcdefg'
print(a, b, c)
>>>a b ['c', 'd', 'e', 'f', 'g']a, *b, c = 'abcdefg'
print(a, b, c)
>>>a ['b', 'c', 'd', 'e', 'f'] g(a, b), (c, d) = (1, 2), (3, 4)
print(a, b, c, d)
>>>1 2 3 4

Dict字典

字典推导析和列表推导具有相同的优点 :

squares_dict = {num : num**2 for num in range(100)}

Python3中keys(),values(),items()返回的是视图对象 :

  • keys()
  • values()
  • items(),返回(key,value)二元元组.
    试图对象既有列表的特性也有迭代器的特性,不会将所有的元素都加载到内存中,但是仍可以使用len()来获取它的长度,in判断元素是否在其中.

实现细节

  Cpython使用伪随机探测(pseudo-random probing)的散列表(hash table)作为字典的底层数据结构.所以只有可hash的对象才能作为字典的键值,如果一个对象有个在整个生命周期都不变的散列值hash value,而且这个值可以和其他对象进行比较,那么这个对象就是可hash的.Python中所有的不可变类型都是可hash的,列表,字典,集合是不可hash的.

定义hash类型的协议包括下面这两种方法:

  • hash:给出字典内部实现需要的散列值(int),用户自定义类的实例对象,有id()给出.
  • eq:比较两个对象的值是否相等,对于用户自定义的类,除了自身,所有的实例对象默认不相等.
>>> map(hash, (0, 1, 2, 3))
[0, 1, 2, 3]
>>> map(hash, ("namea", "nameb", "namec", "named"))
[-1658398457, -1658398460, -1658398459, -1658398462]

散列冲突(hash collision)

  Python字典是使用哈希表实现的,究其本质也是一个数组,其索引是通过哈希函数获得的.散列函数的目标是在数组中均匀分布键,良好的散列函数会最小化小化了冲突的可能,如果两个对象相等,那么它们的散列值一定相等.反之不一定成立,这时冲突就发生了,散列值相等,但是两个对象并不相等.Cpython中使用开放定址法(open addressing)来解决冲突.在构造字典的过程中,当键值(可hash的对象)连续时,hash函数可以很好的工作,但是不连续时会增加碰撞的可能.

开放地址(open addressing)

  开放寻址意思是,当冲突发生的时候,即上图中’z’的情况,索引3已经在数组中被使用,就寻找未被占用的索引,将键值’z’对应的value插入数组中对应的位置.

字典常见操作的时间复杂度

操作 平均复杂度 最坏复杂度
0 获取元素 O(1) O(n)
1 修改元素 O(1) O(n)
2 删除元素 O(1) O(n)
3 复制 O(n) O(n)
4 遍历 O(n) O(n)

注意!!!

  在复制和遍历字典的操作中,最坏情况是字典曾达到的最大元素数目,不是字典当前的元素数目.意思就是如果一个字典原来很大,后来删除了很多元素,遍历仍要花费很长时间.因此如果要频繁删除字典中的元素,同时字典较大,那么最好创建一个新的字典.

字典的缺点和替代方案

  • 缺点:保存元素的顺序和键的添加顺序大多数情况下是不一致的,(连续的整数键值除外,因为连续的整数has后的索引值仍是连续的整数.
  • 替代方案:Python的标准库collections,提供了一个OrderedDict有序的字典.
from collections import OrderedDict
OrderedDict((str(num):num) for num in range(5))

OrderedDict()

set集合

  当元素的顺序不重要的时候,集合是一个不错的数据结构.Python提供了两种集合类型:

  • set():可变,无序,有限的集合,元素唯一
  • frozenset():不可变,无序,元素唯一,可哈希
    • forzenset()可作为字典的键值,也可作为set()或forzenset()中的一个元素
    • set()为可变对象,所以set()不能作为set()和forzenset()中的元素,不然会引发TypeError
  • 集合推导:{num for num in range(10)}
实现细节

  在CPython中,集合其实就是带空值的字典,键值为集合的元素.因此集合元素也是可哈希的,所以集合中的元素也依赖于类似散列表的结构,平均时间复杂度为O(1),最坏的情况O(n).

超越基础集合的类型-collections

  • namedtuple() : 创建元组子类的工厂函数
  • deque : 双端队列,类似列表,是栈和队列的一般化,可以从两端添加/取出元素
  • ChainMap : 类似字典的类
  • Counter : 字典子类,对哈希对象进行计数
  • OrderedDict : 字典子类,创建有序的字典
  • derfaultdict : 字典子类

Python:内置类型相关推荐

  1. 算法与数据结构(part2)--Python内置类型性能分析

    学习笔记,仅供参考 文章目录 算法与数据结构--基于python Python内置类型性能分析 timeit模块 计时器类timeit.Timer 计时器类下的timeit.Timer.timeit方 ...

  2. python内置类型方法_python基础(一)内置类型及方法

    python 内置类型主要包含7大类: 数字 序列 映射 文件 类 实例 异常 其中,最常用数据类型为序列 序列 python中包含7种内建序列 列表(list):由方括号构成,用逗号分隔项目: [a ...

  3. python 类继承list,为什么继承 Python 内置类型会出问题?!

    本文出自"Python为什么"系列,请查看全部文章 不久前,Python猫 给大家推荐了一本书<流畅的Python>(点击可跳转阅读),那篇文章有比较多的"溢 ...

  4. Python——内置类型

    Python定义了丰富的数据类型,包括: 数值型:int, float, complex 序列:(iterable) str, unicode, tuple, list, bytearray, buf ...

  5. Python内置类型——list

    list(列表)是Python内置的可变序列(Sequence)类型,list的对象的方法也都是就地(in-place)更改调用这些方法的列表对象, List的一些细节 可以直接为list的某个下标赋 ...

  6. python内置类型_Python内置对象类型

    核心数字类型: 数字:int,long,float,complex,bool 字符:str,unicode 列表:list 字典:dict 元组:tuple 文件:file 其他类型:集合(set), ...

  7. python内置类型方法_浅析Python数字类型和字符串类型的内置方法

    一.数字类型内置方法 1.1 整型的内置方法 作用 描述年龄.号码.id号 定义方式 x = 10 x = int('10') x = int(10.1) x = int('10.1') # 报错 内 ...

  8. Python内置类型集合set和frozenset

    文章目录 简介 构造 基本使用 交集.并集.差集.对称差集 无交集.子集.超集 运算符 可用于 set 的操作 参考文献 简介 集合对象 set 是由具有唯一性的可哈希对象组成的无序多项集,如 lis ...

  9. Python内置类型—序列

    参考文章:序列类型 --- list, tuple, range python的序列类型分为基本序列类型和附加序列类型,三种基本序列类型有list, tuple, range 对象.附加序列类型二进制 ...

  10. python内置类型和类_python – 内置类型和用户定义之间的不一致

    区别在于内置输入是C编译的代码描述符,而用户定义的函数代表它的代码 descriptors.有关详细信息,请参阅 source. 此外,虽然内置函数及其方法是静态分配的数据结构,但用户定义的数据结构的 ...

最新文章

  1. PHP Hashtable实现源码分析
  2. NOI入门级:算法之动态规划
  3. Git.gitignore规则不生效的解决办法
  4. Java试题库(含答案)
  5. 接口测试工具优缺点总结
  6. 线性方程组解的几何意义
  7. Windows7驱动调试小Tips
  8. 今日头条2018:整改、抗争、扩张
  9. 手表频率测试软件,石英钟表测试仪是一款测量石英钟的灵活的工具
  10. RxHttp 全网Http缓存最优解,完整PDF
  11. 计算机考试中如何设置表格外边框,Excel表格中怎么为单元格区域设置边框
  12. Python时间计算:当天、前一天、月初、月末、季初、季末
  13. watermark知识点
  14. MP-BGP报文详解
  15. 【转】初探计算机视觉的三个源头、兼谈人工智能
  16. Android Launcher启动应用程序流程源码解析
  17. 知识科普系列:关于水下/海底光缆您需要了解的一切
  18. pythonista官网-Pythonista中文文档
  19. 奥的斯OTIS电梯电气原理图一般讲解通则-识图
  20. 网站搭建:从零搭建个人网站教程(4)

热门文章

  1. Map集合类型总结,常见Map集合有哪些?他们的优缺点分别是什么?
  2. Canvas 实现小程序动画
  3. p2093 [国家集训队]JZPFAR
  4. 操作系统就是虚拟机--主内又主外
  5. CentOS配置Nginx官方的Yum源 及yum安装php
  6. 图文混排的几种实现方案
  7. 解决 css 浮动后 父元素高度失效问题
  8. (十六)企业部分之lvs
  9. 利用Keydown事件阻止用户输入
  10. 一键安装服务器系统,一键安装服务器系统