[雪峰磁针石博客]python3快速入门教程9重要的标准库-高级篇

日志

logging模块提供了完整和灵活的日志系统。

import logging
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')

输出如下:

WARNING:root:Warning:config file server.conf not found
ERROR:root:Error occurred
CRITICAL:root:Critical error -- shutting down

默认捕获信息和调试消息不会输出,输出为准错误流。可输出信息到email,数据报文,socket或者HTTP服务器。过滤器可以基于DEBUG、INFO、WARNING、ERROR和CRITICAL选择不同的路由, 。

日志系统可以直接在 Python 代码中定制,也可以不经过应用程序直接在一个用户可编辑的配置文件中加载。

弱引用

Python自动进行内存管理(对大多数的对象进行引用计数和垃圾回收), 在最后一个引用消失后,内存会很快释放。

这个工作方式对大多数应用程序工作良好,但是偶尔对象被别的地方使用时会需要跟踪对象。仅仅为跟踪它们创建引用也会使其长期存在。 weakref 模块提供了不用创建引用的跟踪对象工具,一旦对象不需要时,它自动从弱引用表上删除并触发回调。典型的应用包括捕获难以构造的对象:

>>> import weakref, gc
>>> class A:
...     def __init__(self, value):
...         self.value = value
...     def __repr__(self):
...         return str(self.value)
...
>>> a = A(10)                   # create a reference
>>> d = weakref.WeakValueDictionary()
>>> d['primary'] = a            # does not create a reference
>>> d['primary']                # fetch the object if it is still alive
10
>>> del a                       # remove the one reference
>>> gc.collect()                # run garbage collection right away
0
>>> d['primary']                # entry was automatically removed
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    d['primary']                # entry was automatically removed
  File "C:/python36/lib/weakref.py", line 46, in __getitem__
    o = self.data[key]()
KeyError: 'primary'

列表工具

很多数据结构会用到内置列表类型。然而有时可能需要不同性能的实现。

array 块提供了类似列表的array()对象,它仅仅是存储数据更紧凑。以下的示例演存储双字节无符号整数的数组(类型编码)"H")而非存储16字节Python 整数对象的常规列表:

>>> from array import array
>>> a = array('H', [4000, 10, 700, 22222])
>>> sum(a)
26932
>>> a[1:3]
array('H', [10, 700])

collections模块提供了类似列表的deque()对象,它从左边append和pop更快,但是中间查询更慢。这些对象更适用于队列实现和广度优先的树搜索:

>>> from collections import deque
>>> d = deque(["task1", "task2", "task3"])
>>> d.append("task4")
>>> print("Handling", d.popleft())
Handling task1

unsearched = deque([starting_node])
def breadth_first_search(unsearched):
    node = unsearched.popleft()
    for m in gen_moves(node):
        if is_goal(m):
            return m
        unsearched.append(m)

除了链表的替代实现,该库还提供了bisect这样的模块以操作有序链表:

>>> import bisect
>>> scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]
>>> bisect.insort(scores, (300, 'ruby'))
>>> scores
[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]

heapq模块提供了基于常规链表的堆实现。最小的值总是保持在0。这在希望循环访问最小元素但是不想执行完整列表排序的时候非常有用:

>>> from heapq import heapify, heappop, heappush
>>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
>>> heapify(data)                      # rearrange the list into heap order
>>> heappush(data, -5)                 # add a new entry
>>> [heappop(data) for i in range(3)]  # fetch the three smallest entries
[-5, 0, 1]

十进制浮点数算法

decimal模块提供了Decimal数据类型用于浮点数计算。相比内置的二进制浮点数实现float,这个类型更适用于: * 金融应用和其它需要精确十进制表达的场合, * 控制精度, * 控制四舍五入 * 重要数据, * 其他希望计算结果与手算相符的场合。

例如对70分电话费的5%税计算,十进制浮点数和二进制浮点数计算结果的差别如下。如果在分值上舍入,这个差别就很大:

>>> from decimal import *
>>> round(Decimal('0.70') * Decimal('1.05'), 2)
Decimal('0.74')
>>> round(.70 * 1.05, 2)
0.73

Decimal的结果总是保有结尾的0,自动从两位精度延伸到4位。Decimal重现了手工的数学运算,这就确保了二进制浮点数无法精确保有的数据精度。

Decimal可以执行二进制浮点数无法进行的模运算和等值测试:

>>> Decimal('1.00') % Decimal('.10')
Decimal('0.00')
>>> 1.00 % 0.10
0.09999999999999995

>>> sum([Decimal('0.1')]*10) == Decimal('1.0')
True
>>> sum([0.1]*10) == 1.0
False

decimal提供了高精度算法:

>>> getcontext().prec = 36
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857')

参考资料

links