1.1 解压序列赋值给多个变量
任何序列(或者是可迭代对象)可以通过一个简单的赋值语句解压并赋值给多个变量。唯一的前提就是变量必须跟序列元素的数量是一样的。
1.2 解压可迭代对象赋值给多个变量
“表达式”
以下代码中使用的“args”,如果去掉*,是会报错的。
records = [('foo',1,2),('bar','hello'),('foo',3,4)]
for tag,*args in records:
print(tag,*args)
拆分操作,和split结合使用,会实现非常好用的功能:
line = 'nobody:*:-2:-2:Unprivileged User:/Var/empty:/usr/bin/false'
uname,*fields,homedir,sh = line.split(':')
1.3 保留最后N个元素
使用deque(maxlen=N)构造函数会新建一个固定大小的队列,有新元素添加时,会自动删除最老的记录。
from collections import deque
q = deque()
q.append(1)
q.append(2)
q.append(3)
print(q)
q.append(4)#右边添加元素
q.appendleft(0)#左边添加元素
print(q)
q.pop()#删除最右边元素
print(q)
q.popleft()#删除左边元素
print(q)
不指定长度的时候,则会创建一个无界限的队列
1.4 查找最大或最小的N个元素
heapq模块的:nlargest()和nsmallest()
import heapq
nums = [1,8,2,23,7,-4,16,23,42,37,2]
print(heapq.nlargest(3,nums))
print(heapq.nsmallest(3,nums))
如果正在寻找最大或者最小的N个元素,且同集合中元素的总数目相比,N很小,那么可以使用以下函数:
nums = [1,8,2,23,7,-4,16,23,42,37,2]
heap = list(nums)
#找到第3小的元素
heapq.heappop(heap)
heapq.heappop(heap)
heapq.heappop(heap)
当所要寻找的元素数量相对较小时,nlargest和nsmallest函数才是最适用的。如果只是简单寻找最大和最小值,那么max和min函数会更快。如果N和集合本身大小差不多,通常更快的方法是先对集合排序,然后进行切片操作( sorted(items)[:N] 和sorted(items)[-N:] )。
1.6 字典中的映射多个值
怎样实现一个键对应多个键的字典(也叫multidict)?
可以用到collections模块中的defaultdict来构造这样的字典。如:
from collections import defaultdict
d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(3)
print(d)
d = defaultdict(set)
d['a'].add(1)
d['a'].add(2)
d['b'].add(3)
print(d)
1.7 字典排序
你想创建一个字典,并且在迭代或序列化这个字典的时候能够控制元素的顺序。
可以用到collections模块中的OrderedDict类,在迭代时它会保持元素被插入时的顺序:
from collections import OrderedDict
d = OrderedDict()
d['foo'] = 1
d['bar'] = 2
d['spam'] = 3
d['grok'] = 4
for key in d:
print(key,d[key])
1.8 字典的运算
怎样在数据字典中执行一些计算操作呢?
zip()函数可以把字典的键和值反转过来
之后再用min,max,sort等函数
1.9 查找两个字典的相同点
怎样在两个字典中寻找相同点?
通过keys()或者items()执行集合操作即可实现:
a = {'x':1,'y':2,'z':3}
b = {'w':10,'x':11,'y':2}
a.keys() & b.keys()
a.keys() - b.keys()
a.items() & b.items()
c = {key:a[key] for key in a.keys() - {'z','w'}}
1.10 删除序列相同元素并保持顺序
怎样在一个序列上面保持元素顺序相同的同时消除重复的值?
如果序列上的值是hashable类型,那么可以简单的利用集合或者生成器来解决这个问题。
若想消除元素不可哈希的序列中的重复元素的话,必须指定一个参数将序列元素变成hashable类型
1.11 命名切片
你的程序已经出现一大堆已无法直视的硬编码切片下标,然后你想清理下代码。
从字符串的固定位置取出具体的数据:
record = '....................100.......513.25..........'
cost = int(record[20:23]) * float(record[30:36])
避免使用许多神秘难懂的硬编码索引,使用切片命名:
shares = slice(20,23)
prices = slice(30,36)
cost = int(record[shares]) * float(record[prices])
slice对象实例s可以通过s.start, s.stop, s.step属性获取实例对象的信息:
a = slice(2,40,5)
a.start
a.stop
a.step
可以通过使用indices(size)方法将切片映射到特定大小的序列上,会返回一个(start, stop, step)元组。
s = 'HelloWorld'
a.indices(len(s))
for i in range(*a.indices(len(s))):
print(s[i])
1.12 序列中出现次数最多的元素
怎么找出一个序列中出现次数最多的元素呢?
collections模块中的Counter类:
words = ["twinkle", "twinkle", "little", "star",
"how", "i", "wonder", "what", "you", "are",
"up", "above", "the", "world", "so", "high",
"like", "a", "diamond", "in", "the", "sky",
"twinkle", "twinkle", "little", "star",
"how", "i", "wonder", "what", "you", "are"]
from collections import Counter
wordsCounts = Counter(words)
top_three = wordsCounts.most_common(3)
1.13 通过某个关键字排序一个字典列表
你有一个字典列表,你想根据某个或者某几个字典字段来排序这个列表。
通过使用 operator 模块的 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}
]
根据任意的字典字段来排序输入结果行是很容易实现的,代码示例:
from operator import itemgetter
rows_by_fname = sorted(rows, key=itemgetter('fname'))
rows_by_uid = sorted(rows, key=itemgetter('uid'))
print(rows_by_fname)
print(rows_by_uid)
代码的输出如下:
[{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'},
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'},
{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'},
{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'}]
[{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'},
{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'},
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'},
{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'}]
1.14 排序不支持原生比较的对象
你想排序类型相同的对象,但是他们不支持原生的比较操作
内置的 sorted() 函数有一个关键字参数 key ,可以传入一个 callable 对象给它, 这个 callable 对象对每个传入的对象返回一个值,这个值会被 sorted 用来排序这些对象。
1.15 通过某个字段将记录分组
你有一个字典或者实例的序列,然后你想根据某个特定的字段比如 date 来分组迭代访问。
现在假设你想在按 date 分组后的数据块上进行迭代。为了这样做,你首先需要按照指定的字段(这里就是 date )排序, 然后调用 itertools.groupby() 函。
groupby() 函数扫描整个序列并且查找连续相同值(或者根据指定 key 函数返回值相同)的元素序列。 在每次迭代的时候,它会返回一个值和一个迭代器对象, 这个迭代器对象可以生成元素值全部等于上面那个值的组中所有对象。
一个非常重要的准备步骤是要根据指定的字段将数据排序。 因为 groupby() 仅仅检查连续的元素,如果事先并没有排序完成的话,分组函数将得不到想要的结果。
1.16过滤序列元素:
你有一个数据序列,想利用一些规则从中提取出需要的值或者是缩短序列
使用列表推导的一个潜在缺陷就是如果输入非常大的时候会产生一个非常大的结果集,占用大量内存。 如果你对内存比较敏感,那么你可以使用生成器表达式迭代产生过滤的元素。比如:
>>> mylist = [1, 4, -5, 10, -7, 2, 3, -1]
>>> pos = (n for n in mylist if n > 0)
>>> pos
<generator object <genexpr> at 0x1006a0eb0>
>>> for x in pos:
... print(x)
...
1
4
10
2
3
1.17 从字典中提取子集
你想构造一个字典,它是另外一个字典的子集。
最简单的方式是使用字典推导。比如:
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}
# Make a dictionary of all prices over 200
p1 = {key: value for key, value in prices.items() if value > 200}
# Make a dictionary of tech stocks
tech_names = {'AAPL', 'IBM', 'HPQ', 'MSFT'}
p2 = {key: value for key, value in prices.items() if key in tech_names}
1.18 映射名称到序列元素
你有一段通过下标访问列表或者元组中元素的代码,但是这样有时候会使得你的代码难以阅读, 于是你想通过名称来访问元素。
1.19 转换并同时计算数据
你需要在数据序列上执行聚集函数(比如 sum() , min() , max() ), 但是首先你需要先转换或者过滤数据
一个非常优雅的方式去结合数据计算与转换就是使用一个生成器表达式参数。 比如,如果你想计算平方和,可以像下面这样做:
nums = [1, 2, 3, 4, 5]
s = sum(x * x for x in nums)
下面是更多的例子:
# Determine if any .py files exist in a directory
import os
files = os.listdir('dirname')
if any(name.endswith('.py') for name in files):
print('There be python!')
else:
print('Sorry, no python.')
# Output a tuple as CSV
s = ('ACME', 50, 123.45)
print(','.join(str(x) for x in s))
# Data reduction across fields of a data structure
portfolio = [
{'name':'GOOG', 'shares': 50},
{'name':'YHOO', 'shares': 75},
{'name':'AOL', 'shares': 20},
{'name':'SCOX', 'shares': 65}
]
min_shares = min(s['shares'] for s in portfolio)
1.20 合并多个字典或映射
现在有多个字典或者映射,你想将它们从逻辑上合并为一个单一的映射后执行某些操作, 比如查找值或者检查某些键是否存在。
假如你有如下两个字典:
a = {'x': 1, 'z': 3 }
b = {'y': 2, 'z': 4 }
现在假设你必须在两个字典中执行查找操作(比如先从 a 中找,如果找不到再在 b 中找)。 一个非常简单的解决方案就是使用 collections 模块中的 ChainMap 类。比如:
from collections import ChainMap
c = ChainMap(a,b)
print(c['x']) # Outputs 1 (from a)
print(c['y']) # Outputs 2 (from b)
print(c['z']) # Outputs 3 (from a)







网友评论