.. include:: ../LINKS.rst .. _tut-brieftourtwo: ************************************************************************* 标准库的简明介绍(第二部分) ************************************************************************* 第二部分涵盖了许多关于专业编程需求的高级模块. 这些模块很少出现在小的程序当中. .. _tut-output-formatting: 格式化输出 ============================ :mod:`reprlib` 模块提供了一个面向内容很多或者深度很广的嵌套容器的自定义版本 :func:`repr`, 它只显示缩略图 :: >>> import reprlib >>> reprlib.repr(set('supercalifragilisticexpialidocious')) "set(['a', 'c', 'd', 'e', 'f', 'g', ...])" :mod:`pprint` 模块通过一种能够让解释器读懂的方法, 来对内置的和用户自定义的一些对象的输出进行 更复杂的操作. 当返回的结果大于一行时, "pretty printer" 功能模块会加上断行符和适当的缩进, 以 使数据的结构更加清晰明朗:: >>> import pprint >>> t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta', ... 'yellow'], 'blue']]] ... >>> pprint.pprint(t, width=30) [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta', 'yellow'], 'blue']]] :mod:`textwrap` 模块会根据屏幕的宽度而适当地去调整文本段落:: >>> import textwrap >>> doc = """The wrap() method is just like fill() except that it returns ... a list of strings instead of one big string with newlines to separate ... the wrapped lines.""" ... >>> print(textwrap.fill(doc, width=40)) The wrap() method is just like fill() except that it returns a list of strings instead of one big string with newlines to separate the wrapped lines. :mod:`locale` 模块访问一个包含因特定语言环境而异的数据格式的数据库. locale模块的格式化函数的分组属性, 可以用组别分离器, 直接地去格式化数字:: >>> import locale >>> locale.setlocale(locale.LC_ALL, 'English_United States.1252') 'English_United States.1252' >>> conv = locale.localeconv() # 得到一个常规框架的映射 >>> x = 1234567.8 >>> locale.format("%d", x, grouping=True) '1,234,567' >>> locale.format_string("%s%.*f", (conv['currency_symbol'], ... conv['frac_digits'], x), grouping=True) '$1,234,567.80' .. _tut-templating: 模板化 ================= :mod:`string` 模块包括一个多元化的 :class:`Template` 类, 为用户提供简化了的语法格式, 使其可以方便的编辑. 这样可以使用户自定义自己的程序而不用去修改程序本身. 这种格式使用由 ``$`` 和合法的Python标识(包括文字、数字和下划线)组成的占位符名称. 将这些占位符 包含在一对花括号里时允许周围存在更多的字母或者数字而不用理会是否有空格. 必要时使用 ``$$`` 去表示 单独的 ``$`` :: >>> from string import Template >>> t = Template('${village}folk send $$10 to $cause.') >>> t.substitute(village='Nottingham', cause='the ditch fund') 'Nottinghamfolk send $10 to the ditch fund.' 当一个字典或者关键字参数没有给占位符提供相应的值时, :meth:`substitute` 方法会抛出一个 :exc:`KeyError` 异常. 对于像mail-merge风格的应用程序, 用户可能会提供不完整的数据, 此时, :meth:`safe_substitute` 方法可能会更适合——当数据缺失的时候, 它不会改变占位符:: >>> t = Template('Return the $item to $owner.') >>> d = dict(item='unladen swallow') >>> t.substitute(d) Traceback (most recent call last): . . . KeyError: 'owner' >>> t.safe_substitute(d) 'Return the unladen swallow to $owner.' Template类的子类可以指定一个自己的分隔符. 例如, 现在有一大批文件的重命名工作, 针对的是一个照 片浏览器, 它可能会选择使用百分符号将当前时间、图片的序列号或者文件格式分隔出来作为占位符:: >>> import time, os.path >>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg'] >>> class BatchRename(Template): ... delimiter = '%' >>> fmt = input('Enter rename style (%d-date %n-seqnum %f-format): ') Enter rename style (%d-date %n-seqnum %f-format): Ashley_%n%f >>> t = BatchRename(fmt) >>> date = time.strftime('%d%b%y') >>> for i, filename in enumerate(photofiles): ... base, ext = os.path.splitext(filename) ... newname = t.substitute(d=date, n=i, f=ext) ... print('{0} --> {1}'.format(filename, newname)) img_1074.jpg --> Ashley_0.jpg img_1076.jpg --> Ashley_1.jpg img_1077.jpg --> Ashley_2.jpg 另一个用于模板化的应用程序是将项目的逻辑按多种输出格式的细节分离开来. 这使得从传统的模板形式转化 为XML文件、纯文本形式和html网页成为了可能. .. _tut-binary-formats: Working with Binary Data Record Layouts ================================================================== :mod:`struct` 模块一些函数, 如 :fun:`pack` 和 :fun:`unpack` 函数去处理长度可变的二进制 记录格式. 下面这个例子演示了如何在不使用 :mod:`zipfile` 模块的情况下去循环得到一个ZIP文件的 标题信息. 包代码 ``H`` 和 ``I`` 分别表示两个和四个字节的无符号数字. 而 ``<`` 则表示它们是标准 大小并以字节大小的顺序排列在后面:: import struct data = open('myfile.zip', 'rb').read() start = 0 for i in range(3): # 显示最开始的3个标题 start += 14 fields = struct.unpack('>> import weakref, gc >>> class A: ... def __init__(self, value): ... self.value = value ... def __repr__(self): ... return str(self.value) ... >>> a = A(10) # 创建一个引用 >>> d = weakref.WeakValueDictionary() >>> d['primary'] = a # 没有创建一个引用 >>> d['primary'] # 如果存在的话获取这个对旬 10 >>> del a # 移除这个引和 >>> gc.collect() # 直接调用回收机制 0 >>> d['primary'] # 调用的入口已经自动被移除了 Traceback (most recent call last): File "", line 1, in d['primary'] # 调用的入口已经自动被移除了 File "C:/python31/lib/weakref.py", line 46, in __getitem__ o = self.data[key]() KeyError: 'primary' .. _tut-list-tools: 处理列表的工具 =========================================== 许多数据的结构都需要用到内置的列表类型. 但有时候需要在可选择地不同呈现方式中进行权衡. :mod:`array` 模块提供了一个 :class:`array()` 对象, 这个对象像一个列表一样存储同一类型的数据, 而且更简洁. 下面这个例子演示了将一组数字以两个字节的无符号整数(类型码 ``H``) 形式存储为一个数组 而不是通常的Python的list对象的16字节的形式:: >>> from array import array >>> a = array('H', [4000, 10, 700, 22222]) >>> sum(a) 26932 >>> a[1:3] array('H', [10, 700]) :mod:`cllections` 模块提供了一个 :class:`deque()` 对象, 它可以像一个列表一样在左边进行 快速的apend和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) 此外, 标准库里也提供了一些其它的工具, 如 :mod:`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')] :mod:`heapq` 模块提供了一些函数通过常规列表去实现堆. 最低层的入口通常都在零处. 这对于重复访 问一些很小的元素但又不想对整个列表进行排序的应用程序来说十分有效:: >>> from heapq import heapify, heappop, heappush >>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0] >>> heapify(data) # 将列表重新整理成堆 >>> heappush(data, -5) # 增加一个新入口 >>> [heappop(data) for i in range(3)] # 取出这三个最小的入口 [-5, 0, 1] .. _tut-decimal-fp: 十进制浮点数的运算 ==================================================== :mod:`decimal` 模块提供了一个 :class:`Decimal` 针对十进制浮点小数运算的数据类型. 与内 置的数据类型 :class:`float` (针对二进制浮点小数) 相比而言, 它对以下几种情况更为有效 * 金融方面的应用程序和其它需要准确显示小数的地方 * 需要精确控制, * 需要四舍五入以满足法制或者监管要求, * 需要跟踪有意义的小数部分, 即精度, 或者, * 一些用户希望结果符合自己的计算要求的应用程序. 例如, 计算七毛钱话费的5%的税收, 用十进制浮点小数和二进制浮点小数, 得到的结果会不同. 如果结果以分 的精确度来舍入的话, 这种差异就会变得很重要:: >>> from decimal import * >>> round(Decimal('0.70') * Decimal('1.05'), 2) Decimal('0.74') >>> round(.70 * 1.05, 2) 0.73 :class:`Decimal` 的结果会在末尾追加0, 自动从有两位有效数字的乘数相乘中判断应有四位有效数字. 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 精确的显示使得 :class:`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 :mod:`decimal` 模块可以实现各种需求的精度运算:: >>> getcontext().prec = 36 >>> Decimal(1) / Decimal(7) Decimal('0.142857142857142857142857142857142857') .. seealso:: (^.^) - 原文: http://docs.python.org/py3k/tutorial/stdlib2.html - 初译: `刘鑫`_ - 精译: `DocsPy3zh`_ - 校对: `Zoom.Quiet`_ - 复审: