内容简介:以上~大噶元宵节快乐!
写在前面
我又来更新啦~今天一起回顾下Python Cookbook,全书是以 问答对
的形式展开,这是我很久之前看的笔记。Cookbook不算是入门书,更像是一本 工具 书,既然有基础了那就没必要一个个点去看,建议是需要用到那部分就把那块的知识点技巧翻一遍。下面大噶自己查漏补缺吧!
Chap1 数据结构与算法
从任意长度的可迭代对象中分解元素
*表达式
可以用来将一个含有N个元素的数据结构类型分解成所需的几部分。
例如grades保存了100个成绩数据而我们只关心首末两个成绩,就可以把中间的所有成绩保存到一个列表里面,如下:
first, *middle, last = grades
保存最后N个元素
-
collection.deque(maxlen=N)创建了一个固定长度的队列,当有新记录加入而队列已满时会自动移除最老的那条记录。
-
若不指定队列的大小,也就得到了一个无界限的队列;
-
deque支持从队列两端添加或弹出元素
from collection import deque q = deque() q.append(1) q.append(2) q.append(3) q.appendleft(4) q.pop() q.popleft()
找到最大或最小的N个元素
-
heapq模块中有两个函数:nlargest()和nsmallest()
import heapq nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2] print(heapq.nlargest(3, nums)) out: [42, 37, 23] print(heapq.nsmallest(3,nums)) out: [-4, 1, 2]
-
这两个函数还可以接受一个参数key
In [1]: 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} ...: ] cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price']) cheap out: [{'name': 'YHOO', 'price': 16.35, 'shares': 45}, {'name': 'FB', 'price': 21.09, 'shares': 200}, {'name': 'HPQ', 'price': 31.75, 'shares': 35}]
让字典保持有序
-
collection模块的OrderedDict会按照元素初始添加的顺序进行操作;
-
其内部维护了一个双向链表,它会根据元素加入的顺序来排列键的位置。因此OrderedDict的大小是普通字典的2倍多。
字典的计算问题
-
利用zip()将字典的键与值反转
找出序列中出现次数最多的元素
-
collection模块的Counter类
-
并且Counter类有一个非常方便的most_common(n)方法可以直接得到出现次数最多的前几位
from collections import Counter words = [一系列单词组成的列表] word_counts = Counter(words) top_3 = word_counts.most_common(3)
通过公共键对字典列表排序
-
operator模块的itermgetter函数
from operator import itemgetter In [26]: 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} ...: ] itemgetter('fname') Out[31]: <operator.itemgetter at 0x7f01606657d0> rows_by_frame = sorted(rows, key=itemgetter('fname')) Out[30]: [{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]
-
itermgetter()函数还可以接受多个键
rows_by_frame = sorted(rows, key=itemgetter('fname','lname'))
Chap3 数字、日期和时间
对数值进行取整
-
使用内建的round(value, ndigits)函数
>>> round(1.23, 1) 1.2 >>> round(1.27, 1) 1.3 >>> round(162773, -1) 162770
-
当某个值恰好等于两个整数间的一半时,取整操作会去到离该值最近的那个偶数上。如1.5和2.5都会取整到2
-
round()中的ndigits可以是负数,在这种情况下会相应地取整到十位、百位。。。
对数值做格式化输出
-
使用内建的format()函数
>>>x = 123.456 >>>format(x, '0.2f') 123.46
二进制、八进制和十六进制转换
-
要将一个整数转换为二进制,使用bin()
-
要将一个整数转换为八进制,使用oct()
-
要将一个整数转换为十六进制,使用hex()
随机选择
-
random.choice()可以从序列中随机挑选出元素
>>>import random >>>values = [1,2,3,4,5,6] >>>random.choice(values) 4 >>>random.choice(values) 2
-
random.shuffle()可以在序列中原地打乱元素的顺序
>>>random.shuffle(values) >>>values [2,4,3,1,6,5]
-
random.sample()可以取样出N个元素
>>>random.sample(values, 2) [6, 2]
时间换算
-
datatime模块可以用来完成不同时间单位间的换算。例如要表示一个时间间隔,可以创建一个timedelta实例
from datetime import timedelta In [33]: a = timedelta(days=2, hours=6) In [34]: b = timedelta(hours=4.5) In [35]: c = a + b In [36]: c.days Out[36]: 2 In [37]: c.seconds Out[37]: 37800 In [38]: c.seconds/3600 Out[38]: 10.5 In [39]: c.total_seconds() / 3600 Out[39]: 58.5
Chap4 迭代器和生成器
手动访问迭代器中的元素
with open('/etc/passwd') as f: try: while True: line = next(f) print(line, end='') except StopIteration: pass
委托迭代
-
对自定义的容器对象,其内部持有一个列表丶元组或其他的可迭代对象,我们想让自己的新容器能够完成迭代操作。一般来说,我们所要做的就是定义一个__iter__()方法,将迭代请求委托到对象内部持有的容器上。
class Node: def __init__(self, value): Self._value = vaule self._children = [] def __repr__(self): return 'Node({!r})'.format(self._value) def __iter__(self): return iter(self._children)
在这个例子中,iter()方法将迭代请求转发给对象内部持有的_children属性上。
用生成器创建新的迭代模式
-
函数中只要出现了yield语句就会将其转变成一个生成器
def frange(start, stop, increment): x = start while x < stop: yield x x += increment
-
注意生成器只在响应迭代操作时才运行
对迭代器做切片操作
-
itertool.islice()可以对迭代器和生成器做切片操作
In [3]: def count(n): ...: while True: ...: yield n ...: n += 1 ...: In [5]: c = count(0) In [6]: c Out[6]: <generator object count at 0x7f92899b3c80> ----> 1 c[0] TypeError: 'generator' object has no attribute '__getitem__' import itertools In [10]: for x in itertools.islice(c, 10, 20): ...: print(x) 10 11 12 13 14 15 16 17 18 19
跳过可迭代对象中的前一部分元素
-
itertools.dropwhile()函数会 丢弃掉序列中的前面几个元素
例如,我们需要读取一个文件,文件的开头有一系列注释行并不是我们想要的
from itertools import dropwhile with open('/etc/passwd') as f: for line in dropwhile(lambda line: line,startwith('#'), f): print(line, end='')
迭代所有可能的组合
-
我们想对一些列元素的所有可能组合进行迭代
-
itrtools.permutations()函数接受一个元素集合,将其中所有元素重排列为所有可能的情况,并以元组的形式返回。
In [11]: from itertools import permutations In [12]: items = ['a', 'b', 'c'] In [13]: for p in permutations(items): ...: print(p) ...: ('a', 'b', 'c') ('a', 'c', 'b') ('b', 'a', 'c') ('b', 'c', 'a') ('c', 'a', 'b') ('c', 'b', 'a') #如果想得到较短的所有全排列,可以指定长度 In [14]: for p in permutations(items, 2): ...: print(p) ('a', 'b') ('a', 'c') ('b', 'a') ('b', 'c') ('c', 'a') ('c', 'b')
-
itertools.combinations不考虑元素间的实际顺序,即('a', 'b')和('b', 'a')被认为是相同的组合形式。
-
若想解除这一限制,可用combinations_with_replacement。
同时迭代多个序列
-
zip()函数可以用来迭代多个序列中的元素
>>>xvalues = [1,5,4,2,10,7] >>> yvalues = [101,78,37,15,62,99] >>> for x, y in zip(xvalues, yvalues): ... print(x, y) ... 1 101 5 78 4 37 2 15 10 62 7 99
在不同的容器中进行迭代
-
我们需要对许多对象执行相同的操作,但是这些对象包含在不同的容器内,而我们希望可以避免写出嵌套的循环处理,保持代码的可读性。使用itertools.chain()方法可以用来简化这个任务。
from itertools import chain In [18]: a = [1, 2, 3, 4] In [19]: b = ['x', 'y', 'z'] In [20]: for x in chain(a, b): ...: print (x) ...: 1 2 3 4 x y z
合并多个有序序列,再对整个有序序列进行迭代
-
heapq.merge()函数
>>>import heapq >>>a = [1,4,7,10] >>>b = [2,5,6,11] >>>for c in heapq.merge(a,b): ... print(c) ... 1 2 4 5 6 7 10 11
Chap 5 文件和IO
将输出重定向到文件中
-
只需要在print()函数加上file关键字参数即可
with open('somefile.txt', 'rt') as f: print('Hello World!', file=f)
以不同的分隔符或行结尾符完成打印
>>>print('GKY',1995,5,18, sep='-',end='!!\n') GKY-1995-5-18!!
在字符串上执行IO操作
-
使用io.StringIO()和io.ByteIO()来创建类似于文件的对象,这些对象可操作字符串数据。
读写压缩的数据文件
-
gzip和bz2模块可以实现
import gzip with open('somefile.gz', 'rt') as f: text = f.read() import bz2 with open('somefile.bz2', 'rt') as f: text = f.read() import gzip with open('somefile.gz', 'wt') as f: f.write(text) import bz2 with open('somefile.bz', 'wt') as f: f.write(text)
将二进制数据读到可变缓冲区中
-
我们想将二进制数据直接读取到一个可变缓冲区中,中间不经过任何拷贝环节。例如我们想原地修改数据再将它写回到文件中去。
import os.path def read_into_buffer(filename): buf = bytearray(os.path.getsize(filename)) with open(filename, 'rb') as f: f.readinto(buf) return buf with open('sample.bin', 'wb') as f: f.write(b'hello world') buf = read_into_buffer('sample.bin') In [16]: buf Out[16]: bytearray(b'hello world')
序列化 Python 对象
-
我们需要将Python对象序列化为字节流,这样就可以将其保存到文件中、存储到数据库中或者通过网络连接进行传输。
-
序列化数据最常见的做法就是使用pickle模块。
import pickle data = ... #some python object f = open('somefile', 'wb') pickle.dump(data,f)
-
要将对象转存为字符串,可以使用
import pickle data = ... #some python object f = open('somefile', 'wb') pickle.dumps(data,f)
-
如果要从字节流中重新创建出对象,可以使用pickle.load()或者pickle.loads()
Chap 6 数据编码与处理
读写JSON数据
-
主要使用JSON模块
-
两个主要的函数为json.dumps()和json.loads()
-
如果是文件而不是字符串的话使用json.dump()和json.load()
解析简单的XML文档
-
xml.etree.ElementTree可以从简单的XML文档中提取数据
from urllib.request import urlopen from xml.etree.ElementTree import parse u = urlopen('http://planet.python.org/rss20.xml') doc = parse(u) In [24]: for item in doc.iterfind('channel/item'): ....: title = item.findtext('title') ....: date = item.findtext('pubDate') ....: link = item.findtext('link') ....: print (title) ....: print(date) ....: print(link) ....: print() ....:
以上~
大噶元宵节快乐!
本文转载自公众号 NewBeeNLP,作者高开远
推荐阅读
大幅减少GPU显存占用:可逆残差网络(The Reversible Residual Network)
AINLP-DBC GPU 云服务器租用平台建立,价格足够便宜
关于AINLP
AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLP君微信(id:AINLP2),备注工作/研究方向+加群目的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。