zoukankan      html  css  js  c++  java
  • python3 第三十三章

    第二部分提供了更高级的模块用来支持专业编程的需要。这些模块很少出现在小型的脚本里。

    1. 输出格式化
    reprlib 模块提供了一个用来缩写显示大型或深层嵌套容器的 定制版repr() 。

    >>> import reprlib
    >>> reprlib.repr(set('supercalifragilisticexpialidocious'))
    "{'a', 'c', 'd', 'e', 'f', 'g', ...}"

    pprint模块为 打印对解释器可读的 内置和用户自定义的对象 提供了更复杂控制方式.当结果超过一行时,这个"漂亮的打印机"将添加分行符和缩进,以更清楚地显示数据结构:

    >>> import pprint
    >>> t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta',
    ...     'yellow'], 'blue']]]
    ...
    >>> pprint.pprint(t, width=30)
    [[[['black', 'cyan'],
       'white',
       ['green', 'red']],
      [['magenta', 'yellow'],
       'blue']]]

     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.

     locale 模块访问一种特定格式的数据库.local 模块的format函数 的grouping[分组]属性 直接提供一种用 组分隔符 格式化数字的方式:

    >>> import locale
    >>> locale.setlocale(locale.LC_ALL, 'English_United States.1252')
    'English_United States.1252'
    >>> conv = locale.localeconv()          # get a mapping of conventions
    >>> 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'

    2. 模板化

    string 模板包含一个 拥有简化语法适用于客户端用户编辑的 通用的 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.'

     当字典或关键字参数中没有提供 占位符(需要的变量值) 时 substitute()方法将会抛出 KeyError.对于邮件合并样式的应用程序来说,safe_substitute()方法可能更合适, 因为用户提供的数据可能不完整,而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 网页报表。

    3. 使用二进制文件记录数据布局

    struct 模块提供了 pack() 和 unpack() 方法来处理可变长度的二进制记录格式。下面的示例演示如何遍历一个 ZIP 文件的标头信息而无需使用 zipfile 模块。包代码"H" 和 "I"分别表示2个字节和4个字节的无符号数字。"<"表示使用标准大小和小端模式。

    import struct
    
    with open('myfile.zip', 'rb') as f:
        data = f.read()
    
    start = 0
    for i in range(3):                      # show the first 3 file headers
        start += 14
        fields = struct.unpack('<IIIHH', data[start:start+16])
        crc32, comp_size, uncomp_size, filenamesize, extra_size = fields
    
        start += 16
        filename = data[start:start+filenamesize]
        start += filenamesize
        extra = data[start:start+extra_size]
        print(filename, hex(crc32), comp_size, uncomp_size)
    
        start += extra_size + comp_size     # skip to the next header

    4. 多线程

    线程是一种解耦非顺序依赖任务的技术。当其他任务在后台运行时,线程可以用来提高应用程序接受用户输入操作的响应能力。一个相关的使用场景是 I/O 操作与另一个线程中的计算并行执行。

    下面的代码演示了当主程序在运行的同时,高层的 threading 模块可以在后台执行任务。

    import threading, zipfile
    
    class AsyncZip(threading.Thread):
        def __init__(self, infile, outfile):
            threading.Thread.__init__(self)
            self.infile = infile
            self.outfile = outfile
    
        def run(self):
            f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
            f.write(self.infile)
            f.close()
            print('Finished background zip of:', self.infile)
    
    background = AsyncZip('mydata.txt', 'myarchive.zip')
    background.start()
    print('The main program continues to run in foreground.')
    
    background.join()    # Wait for the background task to finish
    print('Main program waited until background was done.')

    多线程应用程序的最主要挑战是协调线程间共享的数据或其他资源。为此目的,该线程模块提供了许多同步原语包括锁、 事件、 条件变量和信号量。

    尽管这些工具很强大,很小的设计错误也可能导致很难复现的问题。因此,任务协调的首选方法是将所有对某个资源的访问集中在单个线程中,然后使用queue模块向该线程提供来自其他线程的请求。使用队列对象进行线程间通信和协调的应用程序更易于设计,更易于阅读和更可靠。

    5. 日志

    logging模块提供了一个全功能和灵活的日志系统。最简单的,日志消息发送到文件或sys.stderr:

    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、 datagrams、sockets发送,或者发送到 HTTP 服务器。新过滤器可以根据消息优先级选择不同的路由:DEBUG、INFO、WARNING,ERROR和CRITICAL。

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

    6. 弱引用

    Python执行自动内存管理(大多数对象采用引用计数和垃圾回收以消除循环)。在最后一个引用消失后,内存会立即释放。

    这个方式对大多数应用程序工作良好,但是有时候会需要跟踪对象,只要它们还被其它地方所使用。不幸的是,只是跟踪它们会创建一个引用,这个引用会一直存在。weakref模块提供了用于跟踪对象的工具,而无需创建引用。当不再需要该对象时,它会自动从 weakref 表中删除并且会为 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:/python35/lib/weakref.py", line 46, in __getitem__
        o = self.data[key]()
    KeyError: 'primary'

    7. 使用列表的工具

    很多数据结构使用内置列表类型就可以满足需求。然而,有时需要其它具有不同性能的替代实现。

    array 模块提供了 array()对象,这个对象像列表一样,它只存储相似的数据并且更加简洁。以下示例显示存储为两个字节无符号二进制数(类型代码“H”)的数字数组,而不是每个条目通常是16个字节的Python int对象的常规列表:

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

    collections 模块提供了一个 deque()对象,像list但是拥有从左边更快的赋值速度和读取速度,但是从中间检索会更慢。这些对象非常适合实现队列和广度优先的树搜索:

    >>> 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模块提供了基于常规列表实现堆的功能。最小的值总是保持在第零个位置。这对于需要循环访问最小元素,但是不想运行完整列表排序的应用非常有用:

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

    8. 十进制浮点算术

    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结果保留结尾的零,从具有两个有效数字的乘数自动推断四个有效数字。通过模拟笔算,避免了当二进制浮点表示十进制数时可能出现的精度问题。

    精确的结果使得 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')
  • 相关阅读:
    解决SharePoint 文档库itemadded eventhandler导致的上传完成后,编辑页面保持报错的问题,错误信息为“该文档已经被编辑过 the file has been modified by...”
    解决SharePoint 2013 designer workflow 在发布的报错“负载平衡没有设置”The workflow files were saved but cannot be run.
    随机实例,随机值
    Spring4笔记
    struts2笔记(3)
    struts2笔记(2)
    获取文本的编码类型(from logparse)
    FileUtil(from logparser)
    DateUtil(SimpleDateFormat)
    struts2笔记
  • 原文地址:https://www.cnblogs.com/mrbug/p/8822943.html
Copyright © 2011-2022 走看看