python cookbook 自营_Python Cookbook总结 1-6 章

看这本书的过程中各种茅塞顿开,但开完后记住的并不多。。。写总结把自己不熟悉的记下来。其中大部分都可以在python2上用,少数python3的。

第一章 数据结构和算法

1.1 保存最后 N 个元素 collections.deque

deque(max_len=N) 创建了一个固定长度的序列,当有新序列加入而队列已满时会自动移除最老的那个记录。若不指定队列的大小,也就得到了一个无限界的队列,可以在两端执行添加和弹出操作。

from collections import deque

q = deque(maxlen=3)

q.append(2)

q.append(3)

q.appendleft(1)

q

Out[18]: deque([1, 2, 3])

q.append(4)

Out[20]: deque([2, 3, 4])

q.pop()

Out[22]: 4

1.2 找出集合中最大或最小的N个元素 heapq

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}]

1.3 在字典中将键映射到多个值上 collections.defaultdict

在字典中将键映射到多个值上也就是一个key对应一个列表或集合中。可以使用defaultdict方便的创建,同时该模块创建的字典会自动初始化第一哦值,这样只需关注添加元素即可。

from collections import defaultdict

d.defaultdict(list)

d['a'].append(1)

d['a'].append(1)

d

out: defaultdict(list, {'a': [1, 1]})

s = defaultdict(set)

s['a'].add(1)

s['a'].add(1)

s['a'].add(2)

s

out: defaultdict(set, {'a': {1, 2}})

1.4 让字典保持有序 collections.OrderedDict

使用OrderedDict 创建的dict 会严格按照初始添加的顺序进行。其内部维护了一个双向链表,它会根据元素加入的顺序来排列键的位置。因此OrderedDict的大小是普通字典的2倍多。

1.5 对切片命名 slice

作为一条基本准则,代码中如果有很多硬编码的索引值,将导致可读性和可维护性都不佳。因此可以使用slice()创建一个切片对象,用在任何允许进行切片操作的地方。

items = [0, 1, 2, 3, 4, 5, 6]

a = slice(2, 4)

Out[24]: [2, 3]

items[a]

Out[25]: [2, 3]

1.6 通过公共键对字典列表排序 operator.itemgetter

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]:

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}]

# 也可以使用lambda 代替 itemgetter, 但itemgetter更快

rows_by_fname = sorted(rows, key=lambda r: r['fname'])

In [34]: rows_by_fname

Out[34]:

[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004},

{'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},

{'fname': 'David', 'lname': 'Beazley', 'uid': 1002},

{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]

1.7 将多个映射合并为单个映射 Chainmap

我们有多个字典或者映射,想在逻辑上将他们合并为一个单独的映射结构。python3 中使用

from collections import ChainMap

a = {'x': 1, 'z': 3}

b = {'y' : 2, 'z' : 4}

c = ChainMap(a,b)

In [5]: c

Out[5]: ChainMap({'z': 3, 'x': 1}, {'z': 4, 'y': 2})

In [6]: print(c['x'])

1

In [7]: print(c['y'])

2

In [8]: print(c['z'])

第二章 字符串和文本

文本过滤和清理 str.translate

s = 'python\fis\tawesome\r\n'

In [10]: s

Out[10]: 'python\x0cis\tawesome\r\n'

In [11]: remap = {

....: ord('\t') : ' ',

....: ord('\f') : ' ',

....: ord('\r') : None # Deleted

}

In [21]: a = s.translate(remap)

In [22]: a

Out[22]: 'python is awesome\n'

第三章 数字丶日期和时间

3.1 分数的计算 fractions.Fraction

from fractions import Fraction

a = Fraction(5, 4)

b = Fraction(7, 16)

c = a + b

In [30]: c.numerator

Out[30]: 27

In [31]: c.denominator

Out[31]: 16

3.2 时间换算 datetime.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

第四章 迭代器和生成器

4.1 手动访问迭代器中的元素 next()函数

with open('/etc/passwd') as f:

line = next(f)

print(line)

4.2 委托迭代 iter()方法

对自定义的容器对象,其内部持有一个列表丶元组或其他的可迭代对象,我们想让自己的新容器能够完成迭代操作。一般来说,我们所要做的就是定义一个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属性上。

4.3 yield from

大意是说 yield from 表达式允许一个生成器代理另一个生成器, 这样就允许生成器被替换为另一个生成器, 子生成器允许返回值。yield from 在涉及写成和给予生成器的并发型高级程序中有着更加重要的作用。

def g1(x):

yield range(x)

def g2(x):

yield from range(x)

it1 = g1(5)

it2 = g2(5)

print( [ x for x in it1] )

#out [range(0, 5)]

print( [ x for x in it2] )

#out [0, 1, 2, 3, 4]

可以看到 , yield返回一个生成器 , 这个生成器就是range自身 , yield from 也返回一个生成器, 这个生成器是由range代理的, yield from 在递归程序中较为常用。

4.4 反向迭代 reversed()

假如想要反向迭代序列中的元素,可以使用内建的 reversed()函数。也可以在自己的类中实现reversed()方法。具体实现类似于iter()方法。

a = [1, 2, ,3 ,4]

for x in reversed(a):

print(x)

4.5 定义带有额外状态的生成器函数

想定义一个生成器函数,但它还涉及一些额外的自定义值,可以通过将self的一些属性放到iter()函数里。这样在迭代的过程中就可以持续的访问内部属性。

4.6 对迭代器做切片操作 itertools.islice

对生成切做切片操作,普通的切片不能用,可以使用itertools.islice()函数

In [3]: def count(n):

...: while True:

...: yield n

...: n += 1

...:

In [5]: c = count(0)

In [6]: c

Out[6]:

----> 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

4.7 迭代所有可能的组合或排列 itertools.permutations, itertools.combinations, itertools.combinations_with_replacement

itertools.permutations 接受一个元素集合,将其中所有的元素重排列为所有可能的情况,并以元组序列的形式返回。combinations 不考虑元素间的实际顺序,同时已经原则过的元素将从从可能的候选元素中移除。若想解除这一限制,可用combinations_with_replacement。

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]: from itertools import combinations

In [16]: for c in combinations(items, 3):

...: print(c)

...:

('a', 'b', 'c')

4.8 在不同的容器中进行迭代 itertools.chain()

我们需要对许多对象执行相同的操作,但是这些对象包含在不同的容器内,而我们希望可以避免写出嵌套的循环处理,保持代码的可读性。使用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

4.9 创建处理数据的管道

定义一些裂小型的生成器函数,每个函数执行特定的独立任务。这样就每次把生成器产生的一批数据处理完。由于处理过程的迭代特性,这里只会用道非常少的内存

4.10 用迭代器取代 while循环

关于内建函数iter(),一个少有人知的特性是他可以选择性接受一个无参的可调用对象以及一个哨兵(结束)值作为输入。例如:

CHUNKSIZE = 8192

def reader(s):

for chunk in iter(lambda: s.recv(CHUNKSIZE), 'b'):

process_data(data)

第五章 文件和 I/O

5.1 在字符串上执行I/O操作 io.StringIO() 和 io.BytesIO()

可以模仿文件输入,下列是StringIO(), BytesIO()和这个的操作是一样的。

In [1]: import io

In [2]: s = io.StringIO()

In [3]: s.write(u'hello world\n')

Out[3]: 12

In [4]: print('This is a test', file=s)

In [6]: s.getvalue()

Out[6]: 'hello world\nThis is a test\n'

5.2 将二进制数据读到可变缓冲区中

我们想将二进制数据直接读取到一个可变缓冲区中,中间不经过任何拷贝环节。例如我们想原地修改数据再将它写回到文件中去。

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')

5.3 将已有的文件描述符包装为文件对象

以python 文件对象来包装这个文件描述符,它与一般打开的文件相比是有区别的。区别在于,文件描述符只是一个由操作系统分配的整数句柄,用来指代某种系统I/O通道。

import os

fd = os.open('somefile.txt', os.O_WRONLY | os.O_CREAT)

f = open(fd, 'wt')

f.write('hello world\n')

f.close()

第六章 数据编码与处理

6.1 读写CSV数据

对大部分类型的CSV数据,都可以用csv库来处理。如csv.reader()、、csv.writer()、csv.DictReader()、csv.DictWriter()

6.2 读写JSON数据

这个比较常见,主要使用的是JSON模块。两个主要的函数为json.dunps 和 json.loads()。如果是对文件进行处理而不是字符串的话,可以选择使用json.dump 和json.load 来编码和解码JSON数据。

6.3 解析简单的XML文档 xml.etree.ElementTree

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()

....:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值