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笔记:第一章 数据结构和算法的更多相关文章

  1. C++ Primer 笔记 第一章

    C++ Primer 学习笔记 第一章 快速入门 1.1 main函数 系统通过调用main函数来执行程序,并通过main函数的返回值确定程序是否成功执行完毕.通常返回0值表明程序成功执行完毕: ma ...

  2. Android开发艺术探索笔记——第一章:Activity的生命周期和启动模式

    Android开发艺术探索笔记--第一章:Activity的生命周期和启动模式 怀着无比崇敬的心情翻开了这本书,路漫漫其修远兮,程序人生,为自己加油! 一.序 作为这本书的第一章,主席还是把Activ ...

  3. Android群英传笔记——第一章:Android体系与系统架构

    Android群英传笔记--第一章:Android体系与系统架构 图片都是摘抄自网络 今天确实挺忙的,不过把第一章的笔记做一下还是可以的,嘿嘿 1.1 Google的生态圈 还是得从Android的起 ...

  4. 《SQL CookBook 》笔记-第一章-检索记录

    目录 第一章 检索记录 1.1检索所有行和列 1.2筛选行 1.3查找满足多个查询条件的行 1.4筛选列 1.5创建列的别名 1.6 在where子句中引用别名列 1.7 串联多列的值 1.8 在se ...

  5. 重温《STL源码剖析》笔记 第一章

    源码之前,了无秘密. --侯杰 经典的书,确实每看一遍都能重新收获一遍: 第一章:STL简介 STL的设计思维:对象的耦合性极低,复用性极高,符合开发封闭原则的程序库. STL的价值:1.带给我们一套 ...

  6. [编程笔记]第一章 C语言概述

    //C语言学习笔记 第一讲 C语言概述 第二讲 基本编程知识 第三讲 运算符和表达式 第四讲 流程控制 第五讲 函数 第六讲 数组 第七讲 指针 第八讲 变量的作用域和存储方式 第九讲 拓展类型 第十 ...

  7. 《css3实战》读书笔记 第一章 基于CSS需求而编写的HTML.

    笔记说明 <CSS3实战手册第3版(影印版)>可以消除Web设计工作的痛苦,并且带给你:HTML--重新入门.如果你是HTML新手,你会学到如何以CSS友好的方式进行基本页面构造.若你是H ...

  8. 读阮一峰老师 es6 入门笔记 —— 第一章

    鉴于最近用 vuejs 框架开发项目,其中有很多涉及到 es6 语法不太理解所以便认真地读了一下这本书. 地址:http://es6.ruanyifeng.com/#README 第一章:let ,c ...

  9. 【js 笔记】读阮一峰老师 es6 入门笔记 —— 第一章

      鉴于最近用 vuejs 框架开发项目,其中有很多涉及到 es6 语法不太理解所以便认真地读了一下这本书. 地址:http://es6.ruanyifeng.com/#README 第一章:let ...

随机推荐

  1. 大数四则运算之减法运算-----c语言版

    /* 分三种情况: 1.减数长度大于被减数 交换减数与被减数,输出负号,方便减 2.减数长度等于被减数(分三种情况) a.减数大于被减数,类似1情况1 b.减数等于被减数,两数相等,直接输出0,完成. ...

  2. iOS开发基础--C语言简述(一)

    先占个坑,回来再补 需要的运行环境,自行搜寻,工具不止一种,不详细叙述. C语言是一门非常重要的编程语言,与硬件底层直接相关,很多语言到最后的接口封装都会选择C语言,因而C语言一直很受欢迎,也务必掌握 ...

  3. html基本介绍,了解html与css,html语法和结构

    一般来说,制作自己第一个网页通常书写的文字是"hello world!你好,全世界",代码如下展示: <!DOCTYPE html> <html lang=&qu ...

  4. Oracle11以后的行列转换

    Oracle11以后,行列转换有了新的方法. 下面的是已经疏通过的代码,请放心使用... With AA as ( Select A,B,C,row_number() over (partition ...

  5. Vue 实现动态路由及登录&404页面跳转控制&页面刷新空白解决方案

    Vue实现动态路由及登录&404页面跳转控制&页面刷新空白解决方案   by:授客 QQ:1033553122   开发环境   Win 10   Vue 2.9.6   node-v ...

  6. (vue操作storage)Vue plugin for work with local storage,session storage and memo

    vue-ls https://www.npmjs.com/package/vue-ls NPM npm install vue-ls --save Yarn yarn add vue-ls Usage ...

  7. KVM-virsh 创建虚拟网络

    创建网络 创建配置文件 vim /etc/libvirt/qemu/networks/nfsnobody.xml #创建一个名为nfsnobody的虚拟网络 <network> <n ...

  8. jQuery---$冲突的解决方案

    $冲突的解决方案 遇到其他js文件也用$包装了函数.可以把jQuery放在后面,并释放下$的控制权,也可以换个字符替代原来的$,例如$$ 或者,jQuery //jQuery释放$的控制权 $$ = ...

  9. Wannafly Winter Camp 2020 Day 6D 递增递增 - dp,组合数学

    给定两个常为 \(n\) 的序列 \(l_i,r_i\),问夹在它们之间 ( \(\forall i, l_i \leq a_i \leq r_i\) ) 的不降序列的元素总和. Solution 先 ...

  10. Python数值运算

    算术运算 a=10 b=2 + 加-两个对象相加 a+b输出结果12 - 减-得到负数或是一个数减去另一个数 a - b输出结果8 * 乘-两个数相乘或是返回一个被重复若干次的字符串 a * b输出结 ...