python3-cookbook笔记:第一章 数据结构和算法
python3-cookbook中每个小节以问题、解决方案和讨论三个部分探讨了Python3在某类问题中的最优解决方式,或者说是探讨Python3本身的数据结构、函数、类等特性在某类问题上如何更好地使用。这本书对于加深Python3的理解和提升Python编程能力的都有显著帮助,特别是对怎么提高Python程序的性能会有很好的帮助,如果有时间的话强烈建议看一下。
本文为学习笔记,文中的内容只是根据自己的工作需要和平时使用写了书中的部分内容,并且文中的示例代码大多直接贴的原文代码,当然,代码多数都在Python3.6的环境上都验证过了的。不同领域的编程关注点也会有所不同,有兴趣的可以去看全文。
python3-cookbook:https://python3-cookbook.readthedocs.io/zh_CN/latest/index.html
1.2 解压可迭代对象赋值给多个变量
此小节主要是对于星号表达式的探讨,当想要将一个可迭代对象的部分元素赋值给某个变量,尤其是这部分元素的数量并不确定时,星号表达式就能很好的排上用场了。
使用场景1:普通的分割赋,需要注意的是,星号表达式的变量为列表类型,即使该变量中的元素为0个。
>>> record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212')
>>> name, email, *phone_numbers = record
>>> name
'Dave'
>>> email
'dave@example.com'
>>> phone_numbers
['773-555-1212', '847-555-1212']
>>> name, email, phone_number1, phone_number2, *others = record
>>> others
[]
>>>
使用场景2:在迭代元素为可变长序列时,星号表达式也很好用。
records = [
('foo', 1, 2),
('bar', 'hello'),
('foo', 3, 4),
] def do_foo(x, y):
print('foo', x, y) def do_bar(s):
print('bar', s) for tag, *args in records:
if tag == 'foo':
do_foo(*args)
elif tag == 'bar':
do_bar(*args)
1.3 保留最后 N 个元素
在迭代操作或者其他操作中,如果想要保留一个有固定元素个数的对象的时候,可以考虑使用collections.deque,它会构造一个固定长度的队列(如果指定了的话),当队列满了之后,如果继续往队列中添加元素,就会删除最老的元素,再添加新的元素进去。deque也有对应的方法在队列的两端添加和弹出元素。虽然可以使用列表等方法实现相同的功能,但deque的性能上是优于列表的插入删除等操作的,当然,具体的场景还是要看个人的使用习惯和选择了,此小节只是给出了另一个值得考虑的解决方案。
>>> from collections import deque
>>> q = deque(maxlen=3)
>>> q.append(1)
>>> q.append(2)
>>> q.append(3)
>>> q
deque([1, 2, 3], maxlen=3)
>>> q.append(4)
>>> q
deque([2, 3, 4], maxlen=3)
>>> q.appendleft(5)
>>> q
deque([5, 2, 3], maxlen=3)
>>> q.pop()
3
>>> q
deque([5, 2], maxlen=3)
>>> q.popleft()
5
>>> q
deque([2], maxlen=3)
>>>
1.4 查找最大或最小的 N 个元素
在一个元素个数比较多的集合中查找最大或最小的N个元素,并且要查找的元素个数相对于集合本身元素个数较小时,可以考虑使用heapq模块中的nlargest和nsmallest函数。需要注意的是如果要查找的元素个数和集合本身的元素个数相近的话,建议使用先排序后切割的方式,如sorted(items)[:N]。
在heapq中,由于它是堆结构的,所以第一个元素永远是最小的,当你想要多次使用集合,并且每次使用集合时可以得到集合的最小元素时,可以考虑使用heapq模块,当然,如果你仅仅是想要得到该集合中的唯一一个最大或最小的元素时,建议直接使用max或min函数。
>>> import heapq
>>> nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
>>> heapq.nlargest(3, nums)
[42, 37, 23]
>>> heapq.nsmallest(3, nums)
[-4, 1, 2]
>>> portfolio = [
{'name': 'IBM', 'shares': 100, 'price': 91.1},
{'name': 'AAPL', 'shares': 50, 'price': 543.22},
{'name': 'FB', 'shares': 200, 'price': 21.09},
{'name': 'HPQ', 'shares': 35, 'price': 31.75},
{'name': 'YHOO', 'shares': 45, 'price': 16.35},
{'name': 'ACME', 'shares': 75, 'price': 115.65}
]
>>> heapq.nlargest(3, portfolio, key=lambda s: s['price'])
[{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]
>>>
>>> heap = list(nums)
>>> heapq.heapify(heap) # 将数据进行堆排序后放入列表中
>>> heap
[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]
>>> heapq.heappop(heap)
-4
>>> heapq.heappop(heap)
1
>>> heapq.heappop(heap)
2
>>>
1.8 字典的运算
如果想要某个字典中键最大(最小)或值最大(最小)的键值对,可以使用zip()函数将键值先反转过来。
>>> prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}
>>> max(zip(prices.values(), prices.keys()))
(612.78, 'AAPL')
>>> min(zip(prices.values(), prices.keys()))
(10.75, 'FB')
>>>
1.11 命名切片
程序中使用下标进行切片的情况还是比较多的,如果下标在使用时写死的话,就会使得程序后期变得难以维护,这时可以考虑将切片的下标换为内置的slice函数,所有的下标切片都可以使用这个函数。
>>> items = [0, 1, 2, 3, 4, 5, 6]
>>> a = slice(2, 4)
>>> items[2:4]
[2, 3]
>>> items[a]
[2, 3]
>>> items[a] = [10, 11]
>>> items
[0, 1, 10, 11, 4, 5, 6]
>>> a.start
2
>>> a.stop
4
>>> a.step
>>>
>>> record = '....................100 .......513.25 ..........'
>>> cost = int(record[20:23]) * float(record[31:37]) # 下标切片写死在代码里,不建议这样做
>>> cost
51325.0
>>> SHARES = slice(20, 23)
>>> PRICE = slice(31, 37)
>>> cost = int(record[SHARES]) * float(record[PRICE])
>>> cost
51325.0
>>>
1.12 序列中出现次数最多的元素
对于一个序列中每个元素的出现次数,当然可以自己手动利用字典去实现,但是最优的选择应该是collections.Counter,它就是专门为这类问题而设计的,Counter对象的底层实现其实也是一个字典,具体使用见示例代码。
>>> from collections import Counter
>>> words = [
'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
'my', 'eyes', "you're", 'under'
]
>>> word_counts = Counter(words)
>>> word_counts.most_common(3) # 出现次数最多的3个单词
[('eyes', 8), ('the', 5), ('look', 4)]
>>> word_counts['eyes']
8
>>> morewords = ['why','are','you','not','looking','in','my','eyes']
>>> for word in morewords:word_counts[word] += 1 # 像字典一样操作Counter对象 >>> word_counts['eyes']
9
>>> word_counts.update(morewords) # 或者使用update方法进行更新
>>> a = Counter(words)
>>> b = Counter(morewords)
>>> c = a + b # 可以使用+/-运算符进行操作
>>> c
Counter({'eyes': 9, 'the': 5, 'look': 4, 'my': 4, 'into': 3, 'not': 2, 'around': 2, "don't": 1, "you're": 1, 'under': 1, 'why': 1, 'are': 1, 'you': 1, 'looking': 1, 'in': 1})
>>>
1.13 通过某个关键字排序一个字典列表
如果想要对一个元素为字典的列表进行排序操作,如sorted/max/min等函数,平常使用对应的lambda表达式即可,但是如果对性能有要求的话,建议使用operator.itemgetter函数。
如果排序的元素不是字典,而是类对象,则可以使用operator.attrgetter,这是1.14节的内容,用法与itemgetter相似,就不贴示例代码了。
>>> from operator import itemgetter
>>> rows = [
{'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
{'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
>>> sorted(rows, key=itemgetter('fname'))
[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]
>>> sorted(rows, key=itemgetter('lname','fname'))
[{'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}]
>>>
1.20 合并多个字典或映射
当你想在多个字典中查找某些键或值的时候可以使用collections.ChainMap,它会将多个字典从逻辑上合并为一个字典,如果多个字典中有相同的键,则对于该键的操作总是对应的拥有该键的第一个字典。需要注意的是对于ChainMap对象的操作是会作用到对应的字典上去的。
>>> from collections import ChainMap
>>> a = {'x': 1, 'z': 3 }
>>> b = {'y': 2, 'z': 4 }
>>> c = ChainMap(a,b)
>>> c['x']
1
>>> c['y']
2
>>> c['z']
3
>>> len(c)
3
>>> list(c.keys())
['x', 'z', 'y']
>>> list(c.values())
[1, 3, 2]
>>> c['z']
3
>>> c['z'] = 10
>>> c['z']
10
>>> c['w'] = 40
>>> c['w']
40
>>> a
{'x': 1, 'z': 10, 'w': 40}
>>>
python3-cookbook笔记:第一章 数据结构和算法的更多相关文章
- C++ Primer 笔记 第一章
C++ Primer 学习笔记 第一章 快速入门 1.1 main函数 系统通过调用main函数来执行程序,并通过main函数的返回值确定程序是否成功执行完毕.通常返回0值表明程序成功执行完毕: ma ...
- Android开发艺术探索笔记——第一章:Activity的生命周期和启动模式
Android开发艺术探索笔记--第一章:Activity的生命周期和启动模式 怀着无比崇敬的心情翻开了这本书,路漫漫其修远兮,程序人生,为自己加油! 一.序 作为这本书的第一章,主席还是把Activ ...
- Android群英传笔记——第一章:Android体系与系统架构
Android群英传笔记--第一章:Android体系与系统架构 图片都是摘抄自网络 今天确实挺忙的,不过把第一章的笔记做一下还是可以的,嘿嘿 1.1 Google的生态圈 还是得从Android的起 ...
- 《SQL CookBook 》笔记-第一章-检索记录
目录 第一章 检索记录 1.1检索所有行和列 1.2筛选行 1.3查找满足多个查询条件的行 1.4筛选列 1.5创建列的别名 1.6 在where子句中引用别名列 1.7 串联多列的值 1.8 在se ...
- 重温《STL源码剖析》笔记 第一章
源码之前,了无秘密. --侯杰 经典的书,确实每看一遍都能重新收获一遍: 第一章:STL简介 STL的设计思维:对象的耦合性极低,复用性极高,符合开发封闭原则的程序库. STL的价值:1.带给我们一套 ...
- [编程笔记]第一章 C语言概述
//C语言学习笔记 第一讲 C语言概述 第二讲 基本编程知识 第三讲 运算符和表达式 第四讲 流程控制 第五讲 函数 第六讲 数组 第七讲 指针 第八讲 变量的作用域和存储方式 第九讲 拓展类型 第十 ...
- 《css3实战》读书笔记 第一章 基于CSS需求而编写的HTML.
笔记说明 <CSS3实战手册第3版(影印版)>可以消除Web设计工作的痛苦,并且带给你:HTML--重新入门.如果你是HTML新手,你会学到如何以CSS友好的方式进行基本页面构造.若你是H ...
- 读阮一峰老师 es6 入门笔记 —— 第一章
鉴于最近用 vuejs 框架开发项目,其中有很多涉及到 es6 语法不太理解所以便认真地读了一下这本书. 地址:http://es6.ruanyifeng.com/#README 第一章:let ,c ...
- 【js 笔记】读阮一峰老师 es6 入门笔记 —— 第一章
鉴于最近用 vuejs 框架开发项目,其中有很多涉及到 es6 语法不太理解所以便认真地读了一下这本书. 地址:http://es6.ruanyifeng.com/#README 第一章:let ...
随机推荐
- Aliyun搭建svn服务器外网访问报错权限配置失败错误
搭建完后所有的配置如下 [root@iZuf655czz7lmtn8v15tsjZ conf]# pwd /home/SVN/conf [root@iZuf655czz7lmtn8v15tsjZ co ...
- Nginx Rewrite相关功能
目录 Nginx Rewrite相关功能 ngx_http_rewrite_module模块指令: if指令: set指令: break指令: return指令: rewrite_log指令: rew ...
- ABP框架迁移到Mysql
ABP框架 .NetCore3.x版本 1.首先找到xxx.Core 项目,添加引用Microsoft.EntityFrameworkCore.Tools 2.找到xxx.EntityFramewor ...
- 有关版本控制--SVN
什么是版本控制? 这个之前有记录过相关的内容 版本管理就是管理更新的历史记录, 它给我们提供了一些在软件开发过程中必不可少的功能,例如: 记录一款软件添加或更改源代码的过程 回滚到特定阶段,恢复误删除 ...
- MySQL必知必会--分 组 数 据
数据分组 目前为止的所有计算都是在表的所有数据或匹配特定的 WHERE 子句的 数据上进行的.提示一下,下面的例子返回供应商 1003 提供的产品数目 但如果要返回每个供应商提供的产品数目怎么办?或者 ...
- 仁和药业顺利出局,布局地产万科A
仁和药业布局到第二单,被止盈了,盈利大约1.1%.这几日地产行业回调明显,所以布局了万科A. 资金量W11.8 建仓价格28.6 加仓系数1.5 加仓间隔2.70% 总盈利比6.50% 期待吧!
- 【Java】模拟登录教务网并获取数据
本文章仅做技术交流演示学习,请勿用于违法操作! 前期准备 首先我们需要到要模拟登录的网页,进行抓包操作. 使用Chrome浏览器打开系统的登录页面,按F12打开开发者工具 切换到Network选项卡 ...
- Ubuntu安装软件时报 Unable to acquire the dpkg frontend lock解决方案
解决方案如下: 对于以上内容,请等待过程完成.如果这没有发生,请在终端中运行: sudo killall apt apt-get 如果以上都不起作用,请删除锁定文件.在终端中运行: sudo rm / ...
- Docker Stack 学习笔记
该文为<深入浅出Docker>的学习笔记,感谢查看,如有错误,欢迎指正 一.简介 Docker Stack 是为了解决大规模场景下的多服务部署和管理,提供了期望状态,滚动升级,简单易用,扩 ...
- linux 开机自启动redis服务
[Unit] Description=The redis-server Process Manager Documentation=https://redis.io/ After=network.ta ...