流畅的python读书笔记-第二章Python 数据结构

列表表达式

>>> symbols = '$¢£¥€¤'
>>> codes = [ord(symbol) for symbol in symbols]
>>> codes
[36, 162, 163, 165, 8364, 164]

生成器表达式(节省内存)

>>> symbols = '$¢£¥€¤'
>>> tuple(ord(symbol) for symbol 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])

元素拆包

latitude, longitude = lax_coordinates # 元组拆包

不用中间变量交换值
b, a = a, b

_用来临时挡住不要的对象
_, filename = os.path.split(‘/home/luciano/.ssh/idrsa.pub’)

平行赋值

>>> a, b, *rest = range(5)
>>> a, b, rest
(0, 1, [2, 3, 4])
>>> a, b, *rest = range(3)
>>> a, b, rest
(0, 1, [2])
>>> a, b, *rest = range(2)
>>> a, b, rest
(0, 1, [])

# 任意位置
>>> a, *body, c, d = range(5)
>>> a, body, c, d
(0, [1, 2], 3, 4)
>>> *head, b, c, d = range(5)
>>> head, b, c, d
([0, 1], 2, 3, 4)

解包

可见在调用参数的时候使用*号可以自动解包

def add(x,y):
    print x+y
para = (1,2)
add(*para)

同理如果是两个星号的话,就是带有**号的字典,自动解包

def add(x,y):
    print x+y
kkwd = {'x' :1,'y':2}
add(**kkwd)

嵌套元素拆包
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)),
]

for name, cc, pop, (latitude, longitude) in metro_areas: # ➋
if longitude <= 0: # ➌
print(fmt.format(name, latitude, longitude))

具名元组

Card = collections.namedtuple(‘Card’, [‘rank’, ‘suit’])

>>> City._fields ➊
('name', 'country', 'population', 'coordinates')
>>> LatLong = namedtuple('LatLong', 'lat long')
>>> delhi_data = ('Delhi NCR', 'IN', 21.935, LatLong(28.613889, 77.208889))
>>> delhi = City._make(delhi_data) ➋
>>> delhi._asdict() ➌
OrderedDict([('name', 'Delhi NCR'), ('country', 'IN'), ('population',
21.935), ('coordinates', LatLong(lat=28.613889, long=77.208889))])
>>> for key, value in delhi._asdict().items():
print(key + ':', value)
name: Delhi NCR
country: IN
population: 21.935
coordinates: LatLong(lat=28.613889, long=77.208889)
>>>

❶ _fields 属性是一个包含这个类所有字段名称的元组。
❷ 用 _make() 通过接受一个可迭代对象来生成这个类的一个实例,它
的作用跟 City(*delhi_data) 是一样的。
❸ _asdict() 把具名元组以 collections.OrderedDict 的形式返
回,我们可以利用它来把元组里的信息友好地呈现出来。

列表或元组的方法和属性(那些由object类支持的方法没有

列出来) page 84

切片

为什么切片和区间会忽略最后一个元素

  • 当只有最后一个位置信息时,我们也可以快速看出切片和区间里有
    几个元素:range(3) 和 my_list[:3] 都返回 3 个元素。
  • 当起止位置信息都可见时,我们可以快速计算出切片和区间的长
    度,用后一个数减去第一个下标(stop – start)即可。
  • 这样做也让我们可以利用任意一个下标来把序列分割成不重叠的两
    部分,只要写成 my_list[:x] 和 my_list[x:] 就可以了,如下所
    示。
>>> l = [10, 20, 30, 40, 50, 60]
>>> l[:2] # 在下标2的地方分割
[10, 20]
>>> l[2:]
[30, 40, 50, 60]
>>> l[:3] # 在下标3的地方分割
[10, 20, 30]
>>> l[3:]
[40, 50, 60]

步进切片

对seq[start:stop:step] 进行求值的时候,Python 会调用
seq.__getitem__(slice(start, stop, step))。

+=

+= 背后的特殊方法是 iadd (用于“就地加法”)。但是如果一个类
没有实现这个方法的话,Python 会退一步调用 add 。考

+= 的概念也适用于 *=,不同的是,后者相对应的
imul

好工具

Python Tutor(http://www.pythontutor.com)是一个对 Python 运行原理进行
可视化分析的工具。

内置函数sorted

一个只有一个参数的函数,这个函数会被用在序列里的每一个元素
上,所产生的结果将是排序算法依赖的对比关键字。

reverse
如果被设定为 True,被排序的序列里的元素会以降序输出

注意并不是简单的把排序结果给反过来,是降序(按照之前的反排序)

数组

  • 如果我们需要一个只包含数字的列表,那么 array.array 比 list 更高效。
  • 数组支持所有跟可变序列有关的操作,包括 .pop、.insert 和.extend。
  • 另外,数组还提供从文件读取和存入文件的更快的方法,如.frombytes 和 .tofile。

示例代码

>>> from array import array ➊
>>> from random import random
>>> floats = array('d', (random() for i in range(10**7))) ➋
>>> floats[-1] ➌
0.07802343889111107
>>> fp = open('floats.bin', 'wb')
>>> floats.tofile(fp) ➍
>>> fp.close()
>>> floats2 = array('d') ➎
>>> fp = open('floats.bin', 'rb')
>>> floats2.fromfile(fp, 10**7) ➏
>>> fp.close()
>>> floats2[-1] ➐
0.07802343889111107
>>> floats2 == floats ➑
True

结论:

  1. array.tofile 和 array.fromfile 用 起来很简单。
  2. 用 array.fromfile 从一个二进制文件里读出 1000 万个 双精度浮点数只需要 0.1 秒,
  3. 这比从文本文件里读取的速度要快 60倍,因为后者会使用内置的 float 方法把每一行文字转换成浮点数。

列表和数组的属性和方法 page110

NumPy 和 SciPy

NumPy 和 SciPy 提供的高阶数组和矩阵操作,Python 成为科学计
算应用的主流语言。

双向队列和其他形式的队列

collections.deque 类(双向队列)是一个线程安全、可以快速从两
端添加或者删除元素的数据类型。

>>> from collections import deque
>>> dq = deque(range(10), maxlen=10) ➊
>>> dq
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
>>> dq.rotate(3) ➋
>>> dq
deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)
>>> dq.rotate(-4)
>>> dq
deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], maxlen=10)
>>> dq.appendleft(-1) ➌
>>> dq
deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
>>> dq.extend([11, 22, 33]) ➍
>>> dq
deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33], maxlen=10)
>>> dq.extendleft([10, 20, 30, 40]) ➎
>>> dq
deque([40, 30, 20, 10, 3, 4, 5, 6, 7, 8], maxlen=10)

❶ maxlen 是一个可选参数,代表这个队列可以容纳的元素的数量
❹ 在尾部添加 3 个元素的操作会挤掉 -1、1 和 2。

列表和双向队列 page 119

小总结

  1. 列表表达式 和 生成器表达式(元祖省内存)很好用
  2. 元祖的拆包十分神奇,尤其是*号的存在
  3. 具名元组的实例也很节省空间,有点像模拟字典使用,._asdict() 方法来把记录变成 OrderedDict 类型
  4. 切片是基本用法,给切片赋值是个好的修改方式
  5. +=
  • 增量赋值 += 和 *= 会区别对待可变和不可变序列。
  • 在遇到不可变序列时,这两个操作会在背后生成新的序列。
  • 但如果被赋值的对象是可变的,那么这个序列会就地修改
  1. sorted 函数,只需要一个比较方法key
  2. 纯数字数组用 array.array比较好,NumPy 和 SciPy科学计算神奇世界
    原文作者:小小梁
    原文地址: https://segmentfault.com/a/1190000014467391
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞