Python 3.9的新增功能展望
在Python3.8的首個正式版發佈一年後,根據Python發版規律最新的Python版本爲3.9,預計將在下個月發佈第一個正式版本。那麼Python 3.9能帶來哪些更新和變化呢,請和蟲蟲一起展望學習一下。
新功能
字典合併和更新運算符
Merge(|)和update(|=)運算符已添加到內置dict類中。
例如:
a = {1: 'a', 2: 'b', 3: 'c'}
b = {4: 'd', 5: 'e'}
c = a | b
print(c)
結果爲:
{1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}
也可以這麼用:
a = {1: 'a', 2: 'b', 3: 'c'}
b = {4: 'd', 5: 'e'}
a |= b
print(a)
結果爲:
{1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}
新的removeprefix()和removesuffix()字符串方法
str.removeprefix(prefix)並且 str.removesuffix(suffix)已添加,可以輕鬆地從字符串中刪除不需要的前綴或後綴。相應的 bytes,bytearray和collections.UserString方法也已添加。
def removeprefix(self: str, prefix: str, /) -> str:
if self.startswith(prefix):
return self[len(prefix):]
else:
return self[:]
def removesuffix(self: str, suffix: str, /) -> str:
# suffix='' should not call self[:-0].
if suffix and self.endswith(suffix):
return self[:-len(suffix)]
else:
return self[:]
內置泛型類型
在類型註釋中,現在可以使用內置的集合類型,例如list和dict作爲通用類型,而不是從中導入相應的大寫類型(例如List或Dict)typing。例如,標準庫中的其他一些類型現在也通用了queue.Queue。
例:
def greet_all(names: list[str]) -> None:
for name in names:
print("Hello", name)
新解析器
Python 3.9使用了一個新的解析器,該解析器基於PEG而不是LL(1)。新解析器的性能大致可與舊解析器媲美,但是在設計新語言功能時,PEG形式主義比LL(1)更靈活。我們將在Python 3.10及更高版本中開始使用這種靈活性。
該ast模塊使用新的解析器,併產生與舊解析器相同的AST。
在Python 3.10中,舊的解析器將被刪除,依賴它的所有功能也將被刪除(主要是parser早已棄用的模塊)。
在Python 3.9中,可以使用命令行開關(-X oldparser)或環境變量(PYTHONOLDPARSER=1)切換回LL(1)解析器。
其他語言的變化
__import__()會拋出ImportError而非ValueError,這通常是在相對導入超出其頂級包時發生。
Python獲取在命令行(例如:python3 script.py)上指定的腳本文件名的絕對路徑,__main__模塊的__file__屬性變爲絕對路徑,而非相對路徑。通過os.chdir()更改當前目錄後,這些路徑仍然有效。副作用是,在這種情況下,回溯還會顯示模塊框架__main__的絕對路徑。
現在,在Python開發模式和調試版本中,將檢查encoding和errors參數是否進行了字符串編碼和解碼操作。例如:open(),str.encode()和 bytes.decode()。
默認情況下,爲了獲得最佳性能,僅在出現第一個編碼/解碼錯誤時才檢查errors參數,並且對於空字符串有時會忽略encoding參數。
".replace("", s, n),現在返回s非零值,而不是空字符串n。和"".replace("", s) 一樣。於此相似,bytes和bytearray對象有類似的變化。
任何有效的表達式現在都可以用爲裝飾器。
改進了對typing模塊的幫助。現在將顯示所有特殊格式和特殊通用別名(如Union和List)的文檔字符串。比如使用help()與範型別名一樣List[int]會顯示對應的具體類型的幫助。
新模塊
zoneinfo
zoneinfo模塊將對IANA時區數據庫的支持引入標準庫。它添加zoneinfo.ZoneInfo了datetime.tzinfo由系統時區數據支持的具體實現。
例:
>>> from zoneinfo import ZoneInfo
>>> from datetime import datetime, timedelta
>>> # Daylight saving time
>>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
>>> print(dt)
2020-10-31 12:00:00-07:00
>>> dt.tzname()
'PDT'
>>> # Standard time
>>> dt += timedelta(days=7)
>>> print(dt)
2020-11-07 12:00:00-08:00
>>> print(dt.tzname())
PST
作爲未提供IANA數據庫的平臺的備用數據源,該tzdata模塊以第一方包的形式發佈-通過PyPI分發並由CPython核心團隊維護。
graphlib
添加graphlib包含graphlib.TopologicalSorter該類的,以提供執行圖的拓撲排序的功能。
標準庫變化
AST
添加了縮進選項,以dump()使其產生多行縮進輸出。ast.unparse()作爲ast模塊中的功能添加,可用於解析ast.AST對象並生成帶有代碼的字符串,該代碼ast.AST在解析時會生成等效的對象。
向包含用於構造該節點的ASDL簽名的AST節點添加了文檔字符串。
asyncio
由於重大安全問題,刪除了asyncio.loop.create_datagram_endpoint()的reuse_address參數支持。由於SO_REUSEADDRUDP中的套接字選項的行爲,更多詳細信息,請參見的文檔loop.create_datagram_endpoint()。
添加了一個新的協程shutdown_default_executor() ,該協程計劃爲等待ThreadPoolExecutor結束關閉的默認執行程序安排關閉時間。另外, asyncio.run()已更新爲使用新的協程。
添加了新的協程 asyncio.to_thread()。主要用於在單獨的線程中運行IO綁定函數,以避免阻塞事件循環,並且本質上run_in_executor()是可以直接使用關鍵字參數的高級版本。
添加了asyncio.PidfdChildWatcher,它是Linux專用的子監視程序實現,用於輪詢進程文件描述符。
compileall
增加hardlink_dupes參數和-hardlink-dupes命令行選項,用於對重複.pyc文件使用硬鏈接的。
在結果.pyc文件中添加了用於路徑操作的新選項:stripdir,prependdir,limit_sl_dest參數以及-s,-p和-e命令行選項。添加了可多次爲優化級別指定選項。
concurrent.futures
添加了一個新的cancel_futures參數,concurrent.futures.Executor. shutdown(),參數將取消所有尚未開始運行的未決futures,而不是在關閉執行程序之前等待它們完成。
從ThreadPoolExecutor 和中刪除了守護進程線程ProcessPoolExecutor。這提高了與子解釋器的兼容性以及其關閉過程的可預測性。
ProcessPoolExecutor的workers實現按需增加,當沒有可用的空閒workers可重用是纔會新添加。該設置優化了啓動開銷,並減少了空閒工作者的CPU時間損失。
curses
添加curses.get_escdelay(),curses.set_escdelay(), curses.get_tabsize(),和curses.set_tabsize()功能。
datetime
isocalendar()和isocalendar()datetime.datetime方法,會返回namedtuple(),而非tuple。
distutils
現在,上載命令將創建SHA2-256和Blake2b-256哈希摘要。它會在阻止MD5摘要的平臺上跳過MD5。
fcntl
新增的常量F_OFD_GETLK,F_OFD_SETLK 和F_OFD_SETLKW。
FTPLIB
構造了給定超時爲零FTP而FTP_TLS會拋出一個ValueError,以防止非阻塞套接字的創建。
GC
當垃圾收集器進行一些對象復活的收集時(在完成終結器之後,可以從隔離的循環之外訪問它們),請不要阻止所有仍無法訪問的對象的收集。
添加了一個新功能,gc.is_finalized()以檢查對象是否已由垃圾收集器完成。
hashlib
內置的哈希模塊現在可以禁用(./configure --without-builtin-hashlib-hashes)或有選擇地啓用。
例如,通過./configure --with-builtin-hashlib-hashes=sha3,blake2
強制使用基於OpenSSL的實現。
HTTP
HTTP狀態代碼hHTTPStatus新添加了“103 EARLY_HINTS” ,“418 IM_A_TEAPO”和“425 TOO_EARLY”。
IDLE和idlelib
添加選項以切換光標閃爍。
退出鍵現在關閉IDLE完成窗口。
將關鍵字添加到模塊名稱完成列表。
以上更改已經移植到了3.8維護版本。
imaplib
IMAP4和IMAP4_SSL支持一個可選的構造函數的超時參數。open()方法有一個可選的超時參數,並且覆蓋的方法到IMAP4_SSL和 IMAP4_stream。
新增加imaplib.IMAP4.unselect()方法用於釋放與所選郵箱關聯的服務器資源,並使服務器返回到已驗證狀態。該命令執行操作與imaplib.IMAP4.close()相同,但unselect()它不會從當前選定的郵箱中永久刪除任何郵件。
importlib
爲了提高與導入語句的一致性,對於無效的導入嘗試,importlib.util.resolve_name()引發ImportError而非ValueError。
inspect
inspect.BoundArguments.arguments從OrderedDict更改爲常規dict.
ipaddress
ipaddress現在支持IPv6範圍地址(帶後綴的IPv6地址%<scope_id>)。
可以使用解析範圍內的IPv6地址ipaddress.IPv6Address。如果存在,則可通過scope_id屬性獲得作用域區域ID。
Math
擴展了math.gcd()函數以處理多個參數。以前,它僅支持兩個參數。
增加math.lcm():返回指定參數的最小公倍數。
增加math.nextafter():將x之後的下一個浮點值 向y返回。
增加math.ulp():返回浮點數的最低有效位的值。
multiprocessing
multiprocessing.SimpleQueue類新增加close()方法明確地關閉隊列。
nntplib
如果給定超時爲零,NNTP和NNTP_SSL會拋出一個ValueError以防止非阻塞套接字的創建。
OS
si_code新增價參數CLD_KILLED和CLD_STOPPED。
公開了Linux特定的os.pidfd_open()和 os.P_PIDFD函數用於使用文件描述符進行進程管理。
os.unsetenv()功能在Windows上也可用。
該os.putenv()和os.unsetenv()功能現在始終可用。
添加os.waitstatus_to_exitcode()功能:將等待狀態轉換爲退出代碼。
pathlib
添加pathlib.Path.readlink(),它表現和os.readlink()類似的行爲。
poplib
如果給定超時爲零,POP3和會拋出一個ValueError,以防止非阻塞套接字的創建。
pprint
pprint現在可以漂亮打印了types.SimpleNamespace。
pydoc
現在不僅針對類,函數,方法等,所有有__doc__屬性的對象都支持。
random
添加一個新random.Random.randbytes方法:生成隨機字節。
signal
公開了Linux專有信息,signal.pidfd_send_signal()用於使用文件描述符而不是pid向進程發送信號。
smtplib
SMTP和MTP_SSL對給定超時爲零設置會拋出一個ValueError,以防止非阻塞套接字的創建。
LMTP構造函數現在具有一個可選的timeout參數。
socket
socket模塊可以CAN_RAW_JOIN_FILTERS 在Linux 4.1及更高版本上導出常量。在支持CAN_J1939協議的平臺上支持該協議。
time
在AIX上,thread_time()現在實現的分辨率爲thread_cputime()納秒,而非clock_gettime(CLOCK_THREAD_CPUTIME_ID)的10毫秒。
sys
添加一個新sys.platlibdir屬性:特定於平臺的庫目錄的名稱。它用於構建標準庫的路徑和已安裝的擴展模塊的路徑。
"lib"在大多數平臺上,它都相等。在Fedora和SuSE上,等於"lib64"在64位平臺上。
以前sys.stderr在非交互式時是塊緩衝的。現在stderr默認爲始終是行緩衝的。
tracemalloc
添加tracemalloc.reset_peak()了將跟蹤的內存塊的峯值大小設置爲當前大小,以測量特定代碼段的峯值。
typing
PEP 593引入了一種typing.Annotated類型,以使用上下文特定的元數據和新include_extras參數 來修飾現有類型,typing.get_type_hints()以在運行時訪問元數據。
unicodedata
Unicode數據庫已更新至版本13.0.0。
VENV
venv現在提供的激活腳本都始終使用所指定的值來一致地指定其提示自定義__VENV_PROMPT__。以前,有些腳本是無條件使用的__VENV_PROMPT__,而其他腳本只有在碰巧被設置的情況下才使用(這是默認情況),而另一種則使用__VENV_NAME__。
XML
現在,當序列化爲xml.etree.ElementTreeXML文件時,可以保留屬性內的空格字符。EOLN不再標準化爲“ n”。這是關於如何解釋XML規範2.11節的討論的結果。
性能優化
優化了用於在理解中分配臨時變量的慣用法。現在,for y in [expr]和一個簡單的任務y = expr一樣快。
例如:sums = [s for s in [0] for x in data for s in [s + x]]
與:=運算符不同,該慣用法不會將變量泄漏到外部作用域。
優化多線程應用程序中的信號處理。如果與主線程不同的線程收到信號,則字節碼評估循環不再在每個字節碼指令處中斷,以檢查無法處理的未決信號。只有主解釋器的主線程可以處理信號。
以前,字節碼評估循環在每條指令處都會中斷,直到主線程處理信號爲止。
使用subprocess來優化FreeBSD上的模塊closefrom()。
以下是從Python 3.4到Python 3.9的性能改進:
結果基於Tools/scripts/var_access_benchmark.py基準腳本,腳本以納秒爲單位顯示計時。基準測試是在運行python.org運行的macOS 64位版本的因特爾 Core i7-4960HQ處理器上進行的 。
許多的Python建宏(range,tuple,set,frozenset,list,dict)現在通過使用加速PEP 590矢量通話協議。
總結
本文我們列出了Python 3.9版本中的代理功能更新和標準庫變化。注意,在正式版本發行前,Python的具體功能草案會不斷地變化,請隨時關注官方文檔。