小结
计时,2021-01-30 21:30-11:30,
python3 的ord,它以一个字符串(Unicode 字符)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值
转换文件的命令 jupyter nbconvert --to markdown E:\PycharmProjects\TianChiProject\00_山枫叶纷飞\competitions\013_fluent_python\CH.02_数据结构-序列构成的数组.ipynb
2.1 内置序列类型概览
Python 标准库用 C 实现了丰富的序列类型,列举如下。
序列类型还能按照存储数据类型来分类
容器序列
list、tuple 和 collections.deque 这些序列能存放不同类型的 数据。
扁平序列
str、bytes、bytearray、memoryview 和 array.array,这类 序列只能容纳一种类型。
容器序列存放的是它们所包含的任意类型的对象的引用,而扁平序列 里存放的是值而不是引用。
换句话说,扁平序列其实是一段连续的内存空间。由此可见扁平序列其实更加紧凑,但是它里面只能存放诸如字 符、字节和数值这种基础类型。
序列类型还能按照能否被修改来进行分类
可变序列
list、bytearray、array.array、collections.deque 和 memoryview。
不可变序列
tuple、str 和 bytes。
2.2 列表推导和生成器表达式
列表推导是构建列表(list)的快捷方式,而生成器表达式则可以用来 创建其他任何类型的序列。
本节摘要:
列表推导不会再有变量泄漏的问题; Python 2.x中,在列表推导中 for 关键词之后的赋值操作可能会影 响列表推导上下文中的同名变量。在 Python 3 中是不 会出现的,列表推导、生成器表达式,以及同它们很相似的集合(set)推导 和字典(dict)推导,在 Python 3 中都有了自己的局部作用域,就 像函数似的。表达式内部的变量和赋值只在局部起作用,表达式的 上下文里的同名变量还可以被正常引用,局部变量并不会影响到它 们。
2.2.2 列表推导同filter和map的比较
symbols = '$¢£¥€¤'
beyond_ascii = [ord(s) for s in symbols if ord(s) > 127]
beyond_ascii
[162, 163, 165, 8364, 164]
beyond_ascii2 = list(filter(lambda x:x>127, map(ord, symbols)))
beyond_ascii2
[162, 163, 165, 8364, 164]
2.2.3 列表表达式嵌套可以实现笛卡儿积
简,略
2.2.4 生成器表达式
优势:逐个产出元素,而不是先构建一个列表再转换数据到构造器函数中——节省一倍内存的占用,比较节省内存
用法:构造器内部for循环,同列表生成器
示例 2-5 用生成器表达式初始化元组和数组
symbols = '$¢£¥€¤'
tuple(ord(s) for s in symbols)
(36, 162, 163, 165, 8364, 164)
import array
array.array('I', (ord(symbol) for symbol in symbols))
array('I', [36, 162, 163, 165, 8364, 164])
2.3 元组不仅仅是不可变的列表
2.3.1 元组和记录 元组其实是对数据的记录:元组中的每个元素都存放了记录中一个字段 的数据,外加这个字段的位置。正是这个位置信息给数据赋予了意义。
% 格式运算符能被匹配到对应的元组元素上。
for 循环可以分别提取元组里的元素,也叫作拆包(unpacking)。因 为元组中第二个元素对我们没有什么用,所以它赋值给“_”占位符。
示例 2-7 把元组用作记录
traveler_ids = [('USA', '31195855'), ('BRA', 'CE342567')]
for passport in sorted(traveler_ids):
print('%s/%s' % passport)
for country, _ in traveler_ids:
print(country)
BRA/CE342567
USA/31195855
2.3.2 元组拆包
拆包:将一个整体拆成多个元素,应用到赋值或者函数的接受参数上。
可以用 * 运算符把一个可迭代对象拆开作为函数的参数
# 正常
lax_coordinates = (33.9425, -118.408056)
latitude, longitude = lax_coordinates # 元组拆包
print(*(latitude, longitude))
33.9425 -118.408056
# divmod Return the tuple (x//y, x%y)
divmod(20, 8)
(2, 4)
t = divmod(20, 8)
quotient, remainder = divmod(*t)
print(quotient, remainder)
0 2
下面是另一个例子,这里元组拆包的用法则是让一个函数可以用元组的 形式返回多个值,然后调用函数的代码就能轻松地接受这些返回值。比 如 os.path.split() 函数就会返回以路径和最后一个文件名组成的元 组 (path, last_part):
import os
_, file_name = os.path.split('C:/1/2/3/3/my.file')
file_name
'my.file'
在Python中, 函数用 *args 来获取不确定数量的参数
在元组拆包中使用 * 也可以帮助我们把注意力集中在元组的 部分元素上。 用*来处理剩下的元素:
a,b, *rest = range(5)
a,b, rest
(0, 1, [2, 3, 4])
print('我又回去了~~')
a,b, *rest
我又回去了~~
(0, 1, 2, 3, 4)
2.3.3 嵌套元组拆包
metro_areas = [ ('Tokyo','JP',36.933,(35.689722,139.691667)), ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)), ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)), ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)), ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833))]
# 表头
print('{:15} | {:^9} | {:^9}'.format('', 'lat.', 'long.'))
# 内容
fmt = '{:15} | {:9.4f} | {:9.4f}'
for name, cc, pop, (latitude, longitude) in metro_areas:
if longitude <= 0:
print(fmt.format(name, latitude, longitude))
| lat. | long.
Mexico City | 19.4333 | -99.1333
New York-Newark | 40.8086 | -74.0204
Sao Paulo | -23.5478 | -46.6358
2.3.4 具名元组 (工厂函数:快速一个基于元组的数据的类)
collections.namedtuple 是一个工厂函数,它可以用来构建一个带字段名的元组和一个有名字的类。
定义:
创建一个具名元组需要两个参数,一个是类名,另一个是类的各个 字段的名字。后者可以是由数个字符串组成的可迭代对象,或者是由空 格分隔开的字段名组成的字符串。
存放在对应字段里的数据要以一串参数的形式传入到构造函数中 (注意,元组的构造函数却只接受单一的可迭代对象)。
可以通过字段名或者位置来获取一个字段的信息。
示例:
from collections import namedtuple
City = namedtuple('city', ['name', 'country', 'population', 'coords'])
tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
tokyo
city(name='Tokyo', country='JP', population=36.933, coords=(35.689722, 139.691667))
tokyo[0]
'Tokyo'
tokyo.name
'Tokyo'
2.3.5 作为不可变列表的元组
和list的区别
除了跟增减元素相关的方法之外,元组支 持列表的其他所有方法。
还有一个例外,元组没有 reversed 方 法,但是这个方法只是个优化而已,reversed(my_tuple) 这个用法在 没有 reversed 的情况下也是合法的。
2.4 切片
2.4.2 对对象进行切片
可以用 s[a