容器序列和扁平序列
- 容器序列
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函数的常用别名