首頁 > Python教程 > Python基礎教程 > Python入門教程之標準庫瀏覽 – Part II

Python入門教程之標準庫瀏覽 – Part II

時間:2019-08-21    來源:互聯網

11. 標準庫瀏覽 – Part II

第二部分包含了支持專業編程工作所需的更高級的模塊,這些模塊很少出現在小腳本中。

11.1. 輸出格式

reprlib 模塊為大型的或深度嵌套的容器縮寫顯示提供了 :repr() 函數的一個定制版本:

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

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

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 模塊按訪問預定好的國家信息數據庫。locale 的格式化函數屬性集提供了一個直接方式以分組標示格式化數字:

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

11.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() 方法可能更適合 — 如果數據不完整,它就不會改變占位符:

 >>> 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.'  

模板子類可以指定一個自定義分隔符。例如,圖像查看器的批量重命名工具可能選擇使用百分號作為占位符,像當前日期,圖片序列號或文件格式:

 >>> 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 WEB 報表定制模板成為可能。

11.3. 使用二進制數據記錄布局

struct 模塊為使用變長的二進制記錄格式提供了 pack() 和 unpack() 函數。下面的示例演示了在不使用 zipfile 模塊的情況下如何迭代一個 ZIP 文件的頭信息。壓縮碼 "H" 和 "I" 分別表示2和4字節無符號數字, "<" 表明它們都是標準大小并且按照 little-endian 字節排序。

 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  

11.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 模塊用那個線程服務其他線程的請求。為內部線程通信和協調而使用 Queue 對象的應用程序更易于設計,更可讀,并且更可靠。

11.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,數據報文,socket 或者 HTTP Server。基于消息屬性,新的過濾器可以選擇不同的路由: DEBUG, INFO, WARNING, ERROR 和 CRITICAL 。

日志系統可以直接在 Python 代碼中定制,也可以不經過應用程序直接在一個用戶可編輯的配置文件中加載。

11.6. 弱引用

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:/python34/lib/weakref.py", line 46, in __getitem__      o = self.data[key]()  KeyError: 'primary'  

11.7. 列表工具

很多數據結構可能會用到內置列表類型。然而,有時可能需要不同性能代價的實現。

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]  

11.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 的結果總是保有結尾的 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')

 

相關推薦
Python入門教程之虛擬環境和包
Python入門教程之標準庫概覽
Python入門簡介 Python能做什么?
調用Python 解釋器 什么是Python 解釋器?
Python3 簡介
Python入門教程之流程控制
Python入門教程之數據結構
Python入門教程之模塊
Python入門教程之輸入和輸出
Python入門教程之錯誤和異常處理
Python入門教程之類
Python入門教程之浮點數算法:爭議和限制

精彩推薦

熱門教程

上海天天彩选4第2018348期 湖北十一选五手机版 如何分分彩走势图怎么下载 闲来广东麻将软件下 广东36选7最新开奖 麻将三人能玩吗 幸运农场奖结果走势图 北京快3形态走势图 一分赛车开奖网址 浙江20选5精准预测 豪利棋牌app送9元 贵州快三走势图基本 河北好运3买五个号多少钱 股票配资平台专业配资就选恒瑞行配资 大满贯Ⅲ李逵劈鱼 申城棋牌最新版下载 11选5万能8码4注包中