常用模块

collections

该模块实现了专门的容器数据类型,为 Python 的通用内置容器、dict、list、set 和 tuple 提供了替代方案。

namedtuple()

用于创建具有命名字段的元组子类的工厂函数

deque

类似列表的容器,两端具有快速追加和弹出

ChainMap

用于创建多个映射的单个视图的类 dict 类

Counter

用于计算可散列对象的 dict 子类

OrderedDict

添加了记住订单条目的 dict 子类

defaultdict

dict 子类调用工厂函数来提供缺失值

UserDict

围绕字典对象的包装器,以便于 dict 子类化

UserList

围绕列表对象的包装器,以便于列表子类化

UserString

围绕字符串对象的包装器,以便于字符串子类化

参考

collections是Python内建的一个集合模块,提供了许多有用的集合类。

namedtuple

我们知道tuple可以表示不变集合,例如,一个点的二维坐标就可以表示成:

>>> p = (1, 2)

但是,看到(1, 2),很难看出这个tuple是用来表示一个坐标的。

定义一个class又小题大做了,这时,namedtuple就派上了用场:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(1, 2)
>>> p.x
1
>>> p.y
2

namedtuple是一个函数,它用来创建一个自定义的tuple对象,并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素。

这样一来,我们用namedtuple可以很方便地定义一种数据类型,它具备tuple的不变性,又可以根据属性来引用,使用十分方便。

可以验证创建的Point对象是tuple的一种子类:

>>> isinstance(p, Point)
True
>>> isinstance(p, tuple)
True

类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple定义:

# namedtuple('名称', [属性list]):
Circle = namedtuple('Circle', ['x', 'y', 'r'])

deque

使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。

deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:

>>> from collections import deque
>>> q = deque(['a', 'b', 'c'])
>>> q.append('x')
>>> q.appendleft('y')
>>> q
deque(['y', 'a', 'b', 'c', 'x'])

deque除了实现list的append()pop()外,还支持appendleft()popleft(),这样就可以非常高效地往头部添加或删除元素。

defaultdict

使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict

>>> from collections import defaultdict
>>> dd = defaultdict(lambda: 'N/A')
>>> dd['key1'] = 'abc'
>>> dd['key1'] # key1存在
'abc'
>>> dd['key2'] # key2不存在,返回默认值
'N/A'

注意默认值是调用函数返回的,而函数在创建defaultdict对象时传入。

除了在Key不存在时返回默认值,defaultdict的其他行为跟dict是完全一样的。

OrderedDict

使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。

如果要保持Key的顺序,可以用OrderedDict

>>> from collections import OrderedDict
>>> d = dict([('a', 1), ('b', 2), ('c', 3)])
>>> d # dict的Key是无序的
{'a': 1, 'c': 3, 'b': 2}
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od # OrderedDict的Key是有序的
OrderedDict([('a', 1), ('b', 2), ('c', 3)])

注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:

>>> od = OrderedDict()
>>> od['z'] = 1
>>> od['y'] = 2
>>> od['x'] = 3
>>> list(od.keys()) # 按照插入的Key的顺序返回
['z', 'y', 'x']

OrderedDict可以实现一个FIFO(先进先出)的dict,当容量超出限制时,先删除最早添加的Key:

from collections import OrderedDict

class LastUpdatedOrderedDict(OrderedDict):

<span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, capacity)</span>:</span>
    super(LastUpdatedOrderedDict, self).__init__()
    self._capacity = capacity

<span class="function"><span class="keyword">def</span> <span class="title">__setitem__</span><span class="params">(self, key, value)</span>:</span>
    containsKey = <span class="number">1</span> <span class="keyword">if</span> key <span class="keyword">in</span> self <span class="keyword">else</span> <span class="number">0</span>
    <span class="keyword">if</span> len(self) - containsKey &gt;= self._capacity:
        last = self.popitem(last=<span class="built_in">False</span>)
        print(<span class="string">'remove:'</span>, last)
    <span class="keyword">if</span> containsKey:
        <span class="keyword">del</span> self[key]
        print(<span class="string">'set:'</span>, (key, value))
    <span class="keyword">else</span>:
        print(<span class="string">'add:'</span>, (key, value))
    OrderedDict.__setitem__(self, key, value)

ChainMap

ChainMap可以把一组dict串起来并组成一个逻辑上的dictChainMap本身也是一个dict,但是查找的时候,会按照顺序在内部的dict依次查找。

什么时候使用ChainMap最合适?举个例子:应用程序往往都需要传入参数,参数可以通过命令行传入,可以通过环境变量传入,还可以有默认参数。我们可以用ChainMap实现参数的优先级查找,即先查命令行参数,如果没有传入,再查环境变量,如果没有,就使用默认参数。

下面的代码演示了如何查找usercolor这两个参数:

from collections import ChainMap
import os, argparse

# 构造缺省参数: defaults = { ‘color’: ‘red’, ‘user’: ‘guest’ }

# 构造命令行参数: parser = argparse.ArgumentParser() parser.add_argument(’-u’, ’–user’) parser.add_argument(’-c’, ’–color’) namespace = parser.parse_args() command_line_args = { k: v for k, v in vars(namespace).items() if v }

# 组合成ChainMap: combined = ChainMap(command_line_args, os.environ, defaults)

# 打印参数: print(‘color=%s’ % combined[‘color’]) print(‘user=%s’ % combined[‘user’])

没有任何参数时,打印出默认参数:

$ python3 use_chainmap.py 
color=red
user=guest

当传入命令行参数时,优先使用命令行参数:

$ python3 use_chainmap.py -u bob
color=red
user=bob

同时传入命令行参数和环境变量,命令行参数的优先级较高:

$ user=admin color=green python3 use_chainmap.py -u bob
color=green
user=bob

Counter

Counter是一个简单的计数器,例如,统计字符出现的个数:

>>> from collections import Counter
>>> c = Counter()
>>> for ch in 'programming':
...     c[ch] = c[ch] + 1
...
>>> c
Counter({'g': 2, 'm': 2, 'r': 2, 'a': 1, 'i': 1, 'o': 1, 'n': 1, 'p': 1})
>>> c.update('hello') # 也可以一次性update
>>> c
Counter({'r': 2, 'o': 2, 'g': 2, 'm': 2, 'l': 2, 'p': 1, 'a': 1, 'i': 1, 'n': 1, 'h': 1, 'e': 1})

Counter实际上也是dict的一个子类,上面的结果可以看出每个字符出现的次数。

小结

collections模块提供了一些有用的集合类,可以根据需要选用。

计数 Counter

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

counter的参数形式

from collections import Counter
c = Counter()                           # a new, empty counter
c = Counter('gallahad')                 # a new counter from an iterable
c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
c = Counter(cats=4, dogs=8)             # a new counter from keyword args
#### 没有的元素会返回0
c = Counter(['eggs', 'ham'])
c['bacon']                              
0
## 删除元素需要用del
c['sausage'] = 0                        # counter entry with a zero count
print(c)
del c['sausage']                        # del actually removes the entry
print(c)
Counter({'eggs': 1, 'ham': 1, 'sausage': 0})
Counter({'eggs': 1, 'ham': 1})
c = Counter(['eggs', 'ham'])
## 返回元素的迭代器,每个元素value是多少就出现多少次,element的顺序是任意的,value 小于1的元素不会被返回. 
c.elements(),list(c.elements())
## 返回value最大的前n个
c.most_common(1)
## .subtract(iterable or mapping),元素相减,未出现的元素会被添加
c.subtract(['eggs','eggs'])
print(c)
c.subtract({'eggs':-2,'ham':3})
print(c)
c.subtract(['milk'])
print(c)
## .update()[iterable-or-mapping],元素相加,未出现的会被添加
c.update(['milk'])
print(c)
(<itertools.chain at 0x26dc0f4f088>, ['eggs', 'ham'])

[('eggs', 1)]

Counter({'ham': 1, 'eggs': -1})
Counter({'eggs': 1, 'ham': -2})
Counter({'eggs': 1, 'milk': -1, 'ham': -2})
Counter({'eggs': 1, 'milk': 0, 'ham': -2})

常用命令

c = Counter(['eggs', 'ham'])
sum(c.values())                 # total of all counts
c.clear()                       # reset all counts
c = Counter(['eggs', 'ham'])
list(c)                         # list unique elements
set(c)                          # convert to a set
dict(c)                         # convert to a regular dictionary
c.items()                       # convert to a list of (elem, cnt) pairs
##Counter(dict(list_of_pairs))    # convert from a list of (elem, cnt) pairs
c.most_common()[:-2-1:-1]       # n least common elements
+c                              # remove zero and negative counts
2

['eggs', 'ham']

{'eggs', 'ham'}

{'eggs': 1, 'ham': 1}

dict_items([('eggs', 1), ('ham', 1)])

[('ham', 1), ('eggs', 1)]

Counter({'eggs': 1, 'ham': 1})

shutil

方法 功能说明
copy(src, dst) 复制文件,新文件具有同样的文件属性,如果目标文件已存在则抛出异常
copy2(src, dst) 复制文件,新文件具有原文件完全一样的属性,包括创建时间、修改时间和最后访问时间等等,如果目标文件已存在则抛出异常
copyfile(src, dst) 复制文件,不复制文件属性,如果目标文件已存在则直接覆盖
copyfileobj(fsrc, fdst) 在两个文件对象之间复制数据,例如copyfileobj(open(‘123.txt’), open(‘456.txt’, ‘a’))
copymode(src, dst) 把src的模式位(mode bit)复制到dst上,之后二者具有相同的模式
copystat(src, dst) 把src的模式位、访问时间等所有状态都复制到dst上
copytree(src, dst) 递归复制文件夹
disk_usage(path) 查看磁盘使用情况
move(src, dst) 移动文件或递归移动文件夹,也可以给文件和文件夹重命名
rmtree(path) 递归删除文件夹
make_archive(base_name, format, root_dir=None, base_dir=None) 创建tar或zip格式的压缩文件
unpack_archive(filename, extract_dir=None, format=None) 解压缩压缩文件

itertools

These tools and their built-in counterparts also work well with the high-speed functions in the operator module. For example, the multiplication operator can be mapped across two vectors to form an efficient dot-product: sum(map(operator.mul, vector1, vector2)).

Iterator

Arguments

Results

Example

count()

start, [step]

start, start+step, start+2*step, …

count(10) --> 10 11 12 13 14 ...

cycle()

p

p0, p1, … plast, p0, p1, …

cycle('ABCD') --> A B C D A B C D ...

repeat()

elem [,n]

elem, elem, elem, … endlessly or up to n times

repeat(10, 3) --> 10 10 10

import itertools
itertools.count(10)
for i in itertools.count(10):
    print(i)
    if i>11:
        break
count(10)

10
11
12
itertools.cycle('abcd')#itetable
a=0
for i in itertools.cycle('abcd'):
    print(i)
    a+=1
    if a>1:
        break
<itertools.cycle at 0x26dc0e34098>

a
b
itertools.repeat('b')#无限的迭代器
itertools.repeat('b',5)
repeat('b')

repeat('b', 5)

Iterators terminating on the shortest input sequence

Iterator

Arguments

Results

Example

accumulate()

p [,func]

p0, p0+p1, p0+p1+p2, …

accumulate([1,2,3,4,5]) --> 1 3 6 10 15

chain()

p, q, …

p0, p1, … plast, q0, q1, …

chain('ABC', 'DEF') --> A B C D E F

chain.from_iterable()

iterable

p0, p1, … plast, q0, q1, …

chain.from_iterable(['ABC', 'DEF']) --> A B C D E F

compress()

data, selectors

(d[0] if s[0]), (d[1] if s[1]), …

compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F

dropwhile()

pred, seq

seq[n], seq[n+1], starting when pred fails

dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1

filterfalse()

pred, seq

elements of seq where pred(elem) is false

filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8

groupby()

iterable[, key]

sub-iterators grouped by value of key(v)

islice()

seq, [start,] stop [, step]

elements from seq[start:stop:step]

islice('ABCDEFG', 2, None) --> C D E F G

starmap()

func, seq

func(*seq[0]), func(*seq[1]), …

starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000

takewhile()

pred, seq

seq[0], seq[1], until pred fails

takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4

tee()

it, n

it1, it2, … itn splits one iterator into n

zip_longest()

p, q, …

(p[0], q[0]), (p[1], q[1]), …

zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-

累加.accumulate()

list(itertools.accumulate(range(5)))
[0, 1, 3, 6, 10]

链式遍历多个迭代器 .chain()

list(itertools.chain(range(5),'abcd')) 
[0, 1, 2, 3, 4, 'a', 'b', 'c', 'd']

链式遍历迭代器中的每个元素 .chain.from_iterable()

list(itertools.chain.from_iterable(['abcd','efgh']))
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

根据一个序列的True/False选择另一个序列 .compress()

list(itertools.compress('abcd',[1,0,0,1]))
['a', 'd']

根据施加于每个元素的条件决定从哪个元素开始迭代 .dropwhile()

从条件不满足的元素开始

list(itertools.dropwhile(lambda x:x>5,range(10)))#第一个元素就失败了
list(itertools.dropwhile(lambda x:x<5,range(10)))
[5, 6, 7, 8, 9]

获取不满足的元素形成的迭代器 .filterfalse()

list(itertools.filterfalse(lambda x:x%2,range(10)))
[0, 2, 4, 6, 8]

.grouby()

groupby()把迭代器中相邻的重复元素挑出来放在一起

实际上挑选规则是通过函数完成的,只要作用于函数的两个元素返回的值相等,这两个元素就被认为是在一组的,而函数返回值作为组的key。如果我们要忽略大小写分组,就可以让元素’A’和’a’都返回相同的key

for key, group in itertools.groupby('AAABBBCCAAA'):
    print(key, list(group))
for key, group in itertools.groupby('AaaBBbcCAAa', lambda c: c.upper()):
     print(key, list(group))
A ['A', 'A', 'A']
B ['B', 'B', 'B']
C ['C', 'C']
A ['A', 'A', 'A']
A ['A', 'a', 'a']
B ['B', 'B', 'b']
C ['c', 'C']
A ['A', 'A', 'a']

.islice() 切片

list(itertools.islice(range(10),3,8,2))
[3, 5, 7]

.starmap() 映射,seq的元素也必须是迭代器

list(itertools.starmap(max,[[1,2,3],[4,5,6],[7,8,9]]))
[3, 6, 9]

.takewhile(pred,iterable) 获取直到条件不满足之前的元素

list(itertools.takewhile(lambda x:x<5,range(10)))
[0, 1, 2, 3, 4]

.tee(iterable,n) 返回n个独立的相同的迭代器

list(map(list,itertools.tee(list(range(10)),5)))
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]

.ziplongest()

##zip是取最短的,这个取最长的,并且可以设置填补值
list(itertools.zip_longest('abcd','123','xyz',fillvalue='-'))
[('a', '1', 'x'), ('b', '2', 'y'), ('c', '3', 'z'), ('d', '-', '-')]

Combinatoric iterators

Iterator

Arguments

Results

product()

p, q, … [repeat=1]

cartesian product, equivalent to a nested for-loop

permutations()

p[, r]

r-length tuples, all possible orderings, no repeated elements

combinations()

p, r

r-length tuples, in sorted order, no repeated elements

combinations_with_replacement()

p, r

r-length tuples, in sorted order, with repeated elements

product('ABCD', repeat=2)

AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD

permutations('ABCD', 2)

AB AC AD BA BC BD CA CB CD DA DB DC

combinations('ABCD', 2)

AB AC AD BC BD CD

combinations_with_replacement('ABCD', 2)

AA AB AC AD BB BC BD CC CD DD

product(seq,repeat=n) 有序排列$A_{n_{seq}}^n$,元素可重复

list(itertools.product('ABCD',repeat=2))
[('A', 'A'),
 ('A', 'B'),
 ('A', 'C'),
 ('A', 'D'),
 ('B', 'A'),
 ('B', 'B'),
 ('B', 'C'),
 ('B', 'D'),
 ('C', 'A'),
 ('C', 'B'),
 ('C', 'C'),
 ('C', 'D'),
 ('D', 'A'),
 ('D', 'B'),
 ('D', 'C'),
 ('D', 'D')]

.permutations(seq,n) 有序排列,元素不可重复

list(itertools.permutations('ABCD',2))
[('A', 'B'),
 ('A', 'C'),
 ('A', 'D'),
 ('B', 'A'),
 ('B', 'C'),
 ('B', 'D'),
 ('C', 'A'),
 ('C', 'B'),
 ('C', 'D'),
 ('D', 'A'),
 ('D', 'B'),
 ('D', 'C')]

.combinations(seq,n) 无序组合,元素不可重复

list(itertools.combinations('ABCD',2))
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')]

.combinations_with_replacement(seq,2) 无序组合,元素可重复

list(itertools.combinations_with_replacement('ABCD',2))
[('A', 'A'),
 ('A', 'B'),
 ('A', 'C'),
 ('A', 'D'),
 ('B', 'B'),
 ('B', 'C'),
 ('B', 'D'),
 ('C', 'C'),
 ('C', 'D'),
 ('D', 'D')]

functools

import functools

partial 偏函数

  • partial(func, *args, **keywords)

    用于创建一个偏函数,将默认参数包装一个可调用对象,返回结果也是可调用对象。 偏函数可以固定住原函数的部分参数,从而在调用时更简单。

int8=functools.partial(int,base=8)
int8('123')
83

.reduce 对每两个元素累积进行函数运算

functools.reduce(lambda x,y:x+y,[1,2,3])
6
上一页
下一页