Python3 cookbook学习笔记-数据结构与算法1

来源:互联网 发布:mac机中钉钉无法登陆 编辑:程序博客网 时间:2024/05/01 21:35

最近在自学python,在大概学习了最基础的语法之后,不知该如何继续,突然发现这本书还不错,读之,记之。


  • 1.1 解压序列赋值给多个变量
  • 1.2 解压可迭代对象赋值给多个变量
  • 1.3 保留最后N个元素
  • 1.4 查找最大或最小的N个元素
  • 1.5 实现一个优先级队列
  • 1.6 字典中的键值映射多个值
  • 1.7 字典排序
  • 1.8 字典的运算
  • 1.9 查找两字典的相同点
  • 1.10 删除序列相同的元素并保持顺序
  • 1.11 命名切片
  • 1.12 序列中出现次数最多的元素
  • 1.13 通过某个关键字排序一个字典列表
  • 1.14 排序不支持原生比较的对象
  • 1.15 通过某个字段将记录分组
  • 1.16 过滤序列元素
  • 1.17 从字典中提取子集
  • 1.18 映射名称到序列元素
  • 1.19 转换并同时计算数据
  • 1.20 合并多个字典或映射

解压序列赋值给多个变量

将一个元组(tuple)中的数据赋值给多个变量:

>>> t = (4,5)>>> x, y = t>>> x4>>> y5

将一个列表(tuple)中的数据赋值给多个变量:

>>> L = ['fww', 33, 170, 72, (1983, 10, 25)]>>> name, age, height, weight, birth = L>>> name'fww'>>> age33>>> height170>>> weight72>>> birth(1983, 10, 25)>>>>>> name, age, height, weight, (year, mon, day) = L>>> year1983>>> mon10>>> day25

如果变量个数和序列元素的个数不匹配,会产生一个异常:

>>> t = (1, 2, 3)>>> a, b = tTraceback (most recent call last):  File "<stdin>", line 1, in <module>ValueError: too many values to unpack (expected 2)>>> a, b, c, d = tTraceback (most recent call last):  File "<stdin>", line 1, in <module>ValueError: not enough values to unpack (expected 4, got 3)>>> a, b, c = t>>> a1>>> b2>>> c3

实际上,这种解压赋值可以用在任何可迭代对象上面,而不仅仅是列表或者元组。 包括 字符串,文件对象,迭代器和生成器。

>>> s = 'hello'>>> a, b, c, d, e = s>>> a'h'>>> b'e'>>> c'l'>>> d'l'>>> e'o'

有时候,你可能只想解压一部分,丢弃其他的值。对于这种情况Python并没有提供特殊 的语法。 但是你可以使用任意变量名去占位,到时候丢掉这些变量就行了。

>>> s = 'world'>>> _, b, c, _, _ = s>>> b'o'>>> c'r'

个人感悟:使用任意变量名去占位这种做法,感觉有点不太舒服。


解压可迭代对象赋值给多个变量

我们已经看到了,如果一个可迭代对象的元素个数超过变量个数时,会抛出一个异常。但是有时候,我们确实不像解压出所有元素,而只是其中的N个元素,怎么办呢?Python的星号表达式可以用来解决这个问题。

>>> record = ('fww', '123@qq.com','12345678911', '010-88888888')>>> name, email, *phone_numbers = record>>> name'fww'>>> email'123@qq.com'>>> phone_numbers['12345678911', '010-88888888']

去掉一个最高分,去掉一个最低分,求其他得分的平均值:

def drop_first_last(grades):     first, *middle, last = grades     return avg(middle)

星号表达式也能用在列表的开始部分:

>>> *trailing, current = [10, 8, 7, 1, 9, 5, 10, 3] >>> trailing[10, 8, 7, 1, 9, 5, 10]>>> current3

星号表达式在迭代元素为可变长元组的序列时是很有用的:

>>> records = [...     ('foo', 1, 2),...     ('bar', 'hello'),...     ('foo', 3, 4)... ]>>> print(records)[('foo', 1, 2), ('bar', 'hello'), ('foo', 3, 4)]>>> for tag, *args in records:...     if tag == 'foo':...         print(*args)...     elif tag == 'bar':...         print(*args)...1 2hello3 4

星号解压语法在字符串操作的时候也会很有用,比如字符串的分割:

>>> line = 'nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false'>>> uname, *fields, homedir, sh = line.split(':')>>> uname'nobody'>>> homedir'/var/empty'>>> sh'/usr/bin/false'

保留最后N个元素

保留有限历史记录正是collections.deque 大显身手的时候,先看看简单的deque 的例子:

>>> from collections import deque>>> q = deque(maxlen=3)>>> q.append(1)>>> q.append(2)>>> q.append(3)>>> qdeque([1, 2, 3], maxlen=3)>>> q.append(4)>>> qdeque([2, 3, 4], maxlen=3)>>> q.append(5)>>> qdeque([3, 4, 5], maxlen=3)

更一般的, deque类可以被用在任何你只需要一个简单队列数据结构的场合。 如果你不 设置最大队列大小,那么就会得到一个无限大小队列,你可以在队列的两端执行添加和弹 出元素的操作。

>>> q = deque()>>> q.append(1)>>> q.append(2)>>> q.append(3)>>> qdeque([1, 2, 3])>>> q.appendleft(4)>>> qdeque([4, 1, 2, 3])>>> q.pop()3>>> qdeque([4, 1, 2])>>> q.popleft()4>>> qdeque([1, 2])

当然你也可以使用列表实现这些操作,但是在队列两端插入或删除元素时间复杂度都是o(1) ,而在列表的开头插入或删除元素的时间复杂度为o(n)。

最后再来看保留最后N个元素的问题:

def search(lines, pattern, history=5):     previous_lines = deque(maxlen=history)     for li in lines:        if pattern in li:            yield li, previous_lines        previous_lines.append(li)

个人感悟:这个例子我没有实际测试,因为初学,对yield的理解还不到位。但基本思路应当是这样:把所有满足条件的记录不断往队列中加,迭代完成后,最后队列中的数据就是最后5个元素。

0 0