容器序列和扁平序列
- 容器序列
list,tuple,collections.deque这些容器内能存放不同数据类型的数据 - 扁平序列
str,bytes,bytearray,memoryview和array.array只能存放同一数据类型
容器内容的可变与不可变
- 可变:
list,bytearray,array.array,collections.deque,memoryview - 不可变
tuple,str,bytes
列表推导
列表推导(list comprehension)简称为listcomps
|
|
- 虽然老生常谈了,但是额外说一句从后往前读非常容易理解
- 使用原则:用列表推导来创建新的列表,并且尽量保持简短
- python会忽略代码里的[], {}, ()中的换行
- 列表推导不一定比
map()和filter()的组合速度慢
生成器表达式
- 生成器表达式的语法跟列表推导差不多,只不过是把方括号
[]变成() - 生成器逐个产生元素, 不会像列表推导一样一次性占用内存, 因此使用生成器表达式可以一定程度上节省内存
*运算符用于拆包
*运算符可以把一个可迭代对象拆开为函数的参数, 用*args来获取不确定数量的参数也是一种经典的写法
|
|
用python打印表格的套路(str.format()函数)
浮点数指定输出位数以及正负号
|
|
指定长度输出与对齐方式, 格式{:*>n}
>: 右对齐(即靠右放置,左边填充)<: 左对齐(即靠左放置, 右边填充)^: 中间对齐(即居中放置, 两遍填充)n: 指定的长度
|
|
以此基础可以打印漂亮的表格
|
|
顺便发现了用来打印表格的库prettytable
namedtuple
创建一个namedtuple需要两个参数,一个是类名,另一个是类的各个属性的名字。后者可以是数个字符串组成的可迭代对象,或者是由空格分隔开的属性名的字符串
|
|
等价于
|
|
切片
在pyton中支持切片的有list, tuple, str
切片的格式为DS[start:stop:step], 左闭右开, 长度为stop - start, 每间隔step位取DS内的元素
|
|
给切片赋值
|
|
序列的增量赋值*=与+=
类能实现+=操作需要实现魔法函数__iadd__(就地加法), 如果没有实现将退一步调用__add__
如果a实现了__iadd__方法, 则a += b将原地进行, 即将b加入到a中, 如果没实现则a = a + b, 之前的a的内存被释放(不同id)
python自带的可变容器都支持+=和*=操作
*=对应__imul__, 思想类似
一个有意思的例子:
|
|
运行上面的代码会发生什么?
上面的例子告诉我们:
- 不要把可变对象放在元组里
- 增量赋值不是一个
原子操作, 虽然抛出了异常但还是完成了操作
list.sort()和内置函数sorted()
list.sort()是就地排序, 返回值是None(一种思想), 从python3.4开始不再支持list.sorted
sorted()会新建一个列表返回
两者都有两个可选的关键字参数, reverse和key, 重点讲key, key为一个只有一个参数的函数, 类似于c++里的cmp, 只传递函数名, 省略括号
bisect
bisect.bisect(haystack, needle), 在haystack(干草堆)里搜索needle(针)的位置, needle插入到这个位置后, haystack还能保持升序.
要求haystack原本有序, 原理为二分查找
bisect.insort(haystack, needle)为找到位置后并插入
不要滥用列表list
- 存放大量的浮点数,
array的效率更高, 同理, 如果我们需要一个只包含数字的列表, 那么array.array比list更高效 - 频繁的对序列做先进先出操作, deque(双端队列)的速度更快
书上一个给人启发的例子
|
|
memoryview
deque
list删除第一个元素或者在第一个元素之前添加一个元素很费时, O(n)? 推荐使用deque, deque是线程安全的
本章的一些不好起标题的知识点
-
交换两个变量的值
a, b = b, a -
如果做的是国际化软件, 那么
_可能就不是一个理想的占位符, 因为它是gettext.gettext函数的常用别名