47、python3.8的新特性
python3.8的新增功能
本文介紹了與3.7相比,Python 3.8的新功能。有關完整的詳細資訊,請參見changelog。
Python 3.8已於2019年10月14日釋出。
新功能
賦值表示式
有一種新語法:=
可將值賦給變數,作為較大表達式的一部分。由於它與海象的眼睛和象牙很像,因此被親切地稱為“海象操作員” 。
在此示例中,賦值表示式有助於避免呼叫 len()
兩次:
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
在正則表示式匹配期間會產生類似的好處,其中需要兩次匹配物件,一次是測試是否發生匹配,另一次是提取子組:
discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
discount = float(mo.group(1)) / 100.0
該運算子對while迴圈也很有用,該迴圈計算一個值以測試迴圈終止,然後在迴圈體中再次需要相同的值:
# Loop over fixed length blocks
while (block := f.read(256)) != '':
process(block)
另一個具有啟發性的用例出現在列表理解中,其中表達式主體中還需要在過濾條件下計算出的值:
[clean_name.title() for name in names if (clean_name := normalize('NFC', name)) in allowed_names]
請儘量將海象運算子的使用限制在清晰的場合中,以降低複雜性並提升可讀性。
看到 有關完整說明,請參見PEP 572。
僅限位置形參
新增了一個函式形參語法 /
用來指明某些函式形參必須使用僅限位置而非關鍵字引數的形式。 這種標記語法與通過 help()
所顯示的使用 Larry Hastings 的 Argument Clinic 工具標記的 C 函式相同。
在下面的例子中,形參 a 和 b 為僅限位置形參,c 或 d 可以是位置形參或關鍵字形參,而 e 或 f 要求為關鍵字形參:
def f(a, b, /, c, d, *, e, f): print(a, b, c, d, e, f)
以下均為合法的呼叫:
f(10, 20, 30, d=40, e=50, f=60)
但是,以下均為不合法的呼叫:
f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument
f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument
這種標記形式的一個用例是它允許純 Python 函式完整模擬現有的用 C 程式碼編寫的函式的行為。 例如,內建的 pow()
函式不接受關鍵字引數:
def pow(x, y, z=None, /):
"Emulate the built in pow() function"
r = x ** y
return r if z is None else r%z
另一個用例是在不需要形參名稱時排除關鍵字引數。 例如,內建的 len()
函式的簽名為 len(obj, /)
。 這可以排除如下這種笨拙的呼叫形式:
len(obj='hello') # The "obj" keyword argument impairs readability
另一個益處是將形參標記為僅限位置形參將允許在未來修改形參名而不會破壞客戶的程式碼。 例如,在 statistics
模組中,形參名 dist 在未來可能被修改。 這使得以下函式描述成為可能:
def quantiles(dist, /, *, n=4, method='exclusive')
...
由於在 /
左側的形參不會被公開為可用關鍵字,其他形參名仍可在 **kwargs
中使用:
>>> def f(a, b, /, **kwargs):
... print(a, b, kwargs)
...
>>> f(10, 20, a=1, b=2, c=3) # a and b are used in two ways
10 20 {'a': 1, 'b': 2, 'c': 3}
這極大地簡化了需要接受任意關鍵字引數的函式和方法的實現。 例如,以下是一段摘自 collections
模組的程式碼:
class Counter(dict):
def __init__(self, iterable=None, /, **kwds):
# Note "iterable" is a possible keyword argument
請參閱 PEP 570 瞭解詳情。
用於已編譯位元組碼檔案的並行檔案系統快取
新增的 PYTHONPYCACHEPREFIX
設定 (也可使用 -X
pycache_prefix
) 可將隱式的位元組碼快取配置為使用單獨的並行檔案系統樹,而不是預設的每個原始碼目錄下的 __pycache__
子目錄。
快取的位置會在 sys.pycache_prefix
中報告 (None
表示預設位置即 __pycache__
子目錄)。
除錯構建使用與釋出構建相同的 ABI
Python 現在不論是以釋出模式還是除錯模式進行構建都將使用相同的 ABI。 在 Unix 上,當 Python 以除錯模式構建時,現在將可以載入以釋出模式構建的 C 擴充套件和使用穩定版 ABI 構建的 C 擴充套件。
釋出構建和除錯構建現在都是 ABI 相容的:定義 Py_DEBUG
巨集不會再啟用 Py_TRACE_REFS
巨集,它引入了唯一的 ABI 不相容性。 Py_TRACE_REFS
巨集添加了 sys.getobjects()
函式和 PYTHONDUMPREFS
環境變數,它可以使用新的 ./configure --with-trace-refs
構建選項來設定。 (由 Victor Stinner 在 bpo-36465 中貢獻。)
在 Unix 上,C 擴充套件不會再被連結到 libpython,但 Android 和 Cygwin 例外。 現在靜態連結的 Python 將可以載入使用共享庫 Python 構建的 C 擴充套件。 (由 Victor Stinner 在 bpo-21536 中貢獻。)
在 Unix 上,當 Python 以除錯模式構建時,匯入操作現在也會查詢在釋出模式下編譯的 C 擴充套件以及使用穩定版 ABI 編譯的 C 擴充套件。 (由 Victor Stinner 在 bpo-36722 中貢獻。)
要將 Python 嵌入到一個應用中,必須將新增的 --embed
選項傳給 python3-config --libs --embed
以獲得 -lpython3.8
(將應用連結到 libpython)。 要同時支援 3.8 和舊版本,請先嚐試 python3-config --libs --embed
並在此命令失敗時回退到 python3-config --libs
(即不帶 --embed
)。
增加一個 pkg-config python-3.8-embed
模組用來將 Python 嵌入到一個應用中: pkg-config python-3.8-embed --libs
包含 -lpython3.8
。 要同時支援 3.8 和舊版本,請先嚐試 pkg-config python-X.Y-embed --libs
並在此命令失敗時回退到 pkg-config python-X.Y --libs
(即不帶 --embed
) (請將 X.Y
替換為 Python 版本號)。
另一方面,pkg-config python3.8 --libs
不再包含 -lpython3.8
。 C 擴充套件不可被連結到 libpython
f-字串支援 =
用於自動記錄表示式和除錯文件
增加 =
說明符用於 f-string。 形式為 f'{expr=}'
的 f-字串將擴充套件表示為表示式文字,加一個等於號,再加表示式的求值結果。 例如:
>>> user = 'eric_idle'
>>> member_since = date(1975, 7, 31)
>>> f'{user=} {member_since=}'
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"
通常的 f-字串格式說明符 允許更細緻地控制所要顯示的表示式結果:
>>> delta = date.today() - member_since
>>> f'{user=!s} {delta.days=:,d}'
'user=eric_idle delta.days=16,075'
=
說明符將輸出整個表示式,以便詳細演示計算過程:
>>> print(f'{theta=} {cos(radians(theta))=:.3f}')
theta=30 cos(radians(theta))=0.866
新增模組
新增的 importlib.metadata
模組提供了從第三方包讀取元資料的(臨時)支援。 例如,它可以提取一個已安裝軟體包的版本號、入口點列表等等:
>>> # Note following example requires that the popular "requests"
>>> # package has been installed.
>>>
>>> from importlib.metadata import version, requires, files
>>> version('requests')
'2.22.0'
>>> list(requires('requests'))
['chardet (<3.1.0,>=3.0.2)']
>>> list(files('requests'))[:5]
[PackagePath('requests-2.22.0.dist-info/INSTALLER'),
PackagePath('requests-2.22.0.dist-info/LICENSE'),
PackagePath('requests-2.22.0.dist-info/METADATA'),
PackagePath('requests-2.22.0.dist-info/RECORD'),
PackagePath('requests-2.22.0.dist-info/WHEEL')]
改進的模組
ast
AST 節點現在具有 end_lineno
和 end_col_offset
屬性,它們給出節點結束的精確位置。 (這隻適用於具有 lineno
和 col_offset
屬性的節點。)
新增函式 ast.get_source_segment()
返回指定 AST 節點的原始碼。
ast.parse()
函式具有一些新的旗標:
type_comments=True
導致其返回與特定 AST 節點相關聯的 PEP 484 和 PEP 526 型別註釋文字;mode='func_type'
可被用於解析 PEP 484 "簽名型別註釋" (為函式定義 AST 節點而返回);feature_version=(3, N)
允許指定一個更早的 Python 3 版本。 (例如,feature_version=(3, 4)
將把async
和await
視為非保留字。)
asyncio
輸入python -m asyncio
將直接發起非同步PEPL,這樣就不需要讓特別緊急的任務處於等待狀態,也不需要再輸入asyncio.run()
來直接呼叫
$ python -m asyncio
asyncio REPL 3.8.0
Use "await" directly instead of "asyncio.run()".
Type "help", "copyright", "credits" or "license" for more information.
>>> import asyncio
>>> await asyncio.sleep(10, result='hello')
hello
在 Windows 上,現在預設的事件迴圈為 ProactorEventLoop
。ProactorEventLoop
現在也支援 UDP。 ProactorEventLoop
現在可通過 KeyboardInterrupt
("CTRL+C") 來中斷。
collections
collections.namedtuple()
的 _asdict()
方法現在將返回 dict
而不是 collections.OrderedDict
。 此項更改是因為普通字典自 Python 3.7 起已保證具有確定的元素順序。 如果還需要 OrderedDict
的額外特性,推薦的解決方案是將結果轉換為需要的型別: OrderedDict(nt._asdict())
。
curses
添加了一個新變數用於儲存下層 ncurses 庫的結構版資訊: ncurses_version
。
datetime
添加了新的替代構造器 datetime.date.fromisocalendar()
和 datetime.datetime.fromisocalendar()
,它們分別基於 ISO 年份、周序號和周內日序號來構造 date
和 datetime
物件;這兩者分別是其所對應類中 isocalendar
方法的逆操作。 (由 Paul Ganssle 在 bpo-36004 中貢獻。)
functools
functools.lru_cache()
現在可直接作為裝飾器而不是作為返回裝飾器的函式。 因此這兩種寫法現在都被支援:
@lru_cache
def f(x):
...
@lru_cache(maxsize=256)
def f(x):
...
添加了一個新的functools.cached_property()裝飾器,用於在例項生命期內快取的計算屬性。
import functools
import statistics
class Dataset:
def __init__(self, sequence_of_numbers):
self.data = sequence_of_numbers
@functools.cached_property
def variance(self):
return statistics.variance(self.data)
gc
get_objects()現在可以接收一個可選的生成引數,指示從中獲取物件的生成
gettext
添加了 pgettext()
及其變化形式
gzip
新增 mtime 形參到 gzip.compress()
用於可重現的輸出。 (由 Guo Ci Teo 在 bpo-34898 中貢獻。)
對於特定型別的無效或已損壞 gzip 檔案現在將引發 BadGzipFile
而不是 OSError
。
idlelib 與 IDLE
超過 N 行(預設值為 50)的輸出將被摺疊為一個按鈕。 N 可以在 Settings 對話方塊的 General 頁的 PyShell 部分中進行修改。 數量較少但是超長的行可以通過在輸出上右擊來摺疊。 被摺疊的輸出可通過雙擊按鈕來展開,或是通過右擊按鈕來放入剪貼簿或是單獨的視窗。
在 Run 選單中增加了 "Run Customized" 以使用自定義設定來執行模組。 輸入的任何命令列引數都會被加入 sys.argv。 它們在下次自定義執行時會再次顯示在窗體中。 使用者也可以禁用通常的 Shell 主模組重啟。
在 IDLE 編輯器視窗中增加了可選的行序號。 視窗開啟時預設不帶行序號,除非在配置對話方塊的 General 選項卡中進行設定。 已開啟視窗中的行序號可以在 Options 選單中顯示和隱藏。
上述修改已被反向移植到 3.7 維護髮行版中。
inspect
inspect.getdoc()
函式現在可以找到 __slots__
的文件字串,如果該屬性是一個元素值為文件字串的 dict
的話。 這提供了類似於目前已有的 property()
, classmethod()
和 staticmethod()
等函式的文件選項:
class AudioClip:
__slots__ = {'bit_rate': 'expressed in kilohertz to one decimal place',
'duration': 'in seconds, rounded up to an integer'}
def __init__(self, bit_rate, duration):
self.bit_rate = round(bit_rate / 1000.0, 1)
self.duration = ceil(duration)
io
在開發模式 (-X
env
) 和除錯構建中,io.IOBase
終結器現在會在 close()
方法失敗時將異常寫入日誌。 發生的異常在釋出構建中預設會被靜默忽略。
json.tool
新增選項 --json-lines
用於將每個輸入行解析為單獨的 JSON 物件。
math
添加了新的函式 math.dist()
用於計算兩點之間的歐幾里得距離。
擴充套件了 math.hypot()
函式以便處理更多的維度。 之前它僅支援 2-D 的情況。
添加了新的函式 math.prod()
作為的 sum()
同類,該函式返回 'start' 值 (預設值: 1) 乘以一個數字可迭代物件的積:
>>> prior = 0.8
>>> likelihoods = [0.625, 0.84, 0.30]
>>> math.prod(likelihoods, start=prior)
0.126
添加了新的函式 math.isqrt()
用於計算整數平方根。
函式 math.factorial()
不再接受非整數類引數。
mmap
mmap.mmap
類現在具有一個 madvise()
方法用於訪問 madvise()
系統呼叫。
multiprocessing
新增 multiprocessing.shared_memory
模組.
在macOS上,現在預設使用的啟動方式是spawn啟動方式。
os
添加了新的 os.memfd_create()
函式用於包裝 memfd_create()
系統呼叫。
在 Windows 上,大部分用於處理重解析點,(包括符號連結和目錄連線)的手動邏輯已被委託給作業系統。 特別地,os.stat()
現在將會遍歷作業系統所支援的任何內容,而 os.lstat()
將只打開被標識為“名稱代理”的重解析點,而其要由 os.stat()
開啟其他的重解析點。 在所有情況下,stat_result.st_mode
將只為符號連結而非其他種類的重解析點設定 S_IFLNK
。 要標識其他種類的重解析點,請檢查新的 stat_result.st_reparse_tag
屬性。
在 Windows 上,os.readlink()
現在能夠讀取目錄連線。 請注意 islink()
會對目錄連線返回 False
,因此首先檢查 islink
的程式碼將連續把連線視為目錄,而會處理 os.readlink()
所引發錯誤的程式碼現在會把連線視為連結。
os.path
返回布林值結果的 os.path
函式例如 exists()
, lexists()
, isdir()
, isfile()
, islink()
, 以及 ismount()
現在對於包含在 OS 層級無法表示的字元或位元組的路徑將會返回 False
而不是引發 ValueError
或其子類 UnicodeEncodeError
和 UnicodeDecodeError
。
expanduser()
on Windows now prefers the USERPROFILE
environment variable and does not use HOME
, which is not normally set for regular user accounts.
isdir()
在 Windows 上不再為不存在的目錄的連結返回真值。
realpath()
在 Windows 上現在會識別重解析點,包括符號連結和目錄連線。
pathlib
返回布林值結果的 pathlib.Path
方法例如 exists()
, is_dir()
, is_file()
, is_mount()
, is_symlink()
, is_block_device()
, is_char_device()
, is_fifo()
, is_socket()
現在對於包含在 OS 層級無法表示的字元或位元組的路徑將會返回 False
而不是引發 ValueError
或其子類 UnicodeEncodeError
。
添加了 pathlib.Path.link_to()
用於建立指向某個路徑的硬連結。
plistlib
添加了新的 plistlib.UID
並啟動了對讀取和寫入經過 NSKeyedArchiver 編碼的二進位制 plists 的支援
py_compile
py_compile.compile()
現在支援靜默模式。
shlex
新增了 shlex.join()
函式作為 shlex.split()
的逆操作。
shutil
shutil.copytree()
現在接受新的 dirs_exist_ok
關鍵字引數。
shutil.make_archive()
現在對新的歸檔預設使用 modern pax (POSIX.1-2001) 格式以提升可移植性和標準一致性,此特性繼承自對 tarfile
模組的相應更改。
shutil.rmtree()
on Windows now removes directory junctions without recursively removing their contents first.
socket
添加了便捷的 create_server()
和 has_dualstack_ipv6()
函式以自動化在建立伺服器套接字時通常情況下所必須的任務,包括在同一套接字中同時接受 IPv4 和 IPv6 連線。
socket.if_nameindex()
, socket.if_nametoindex()
和 socket.if_indextoname()
函式已經在 Windows 上實現。
ssl
增加了 ssl.SSLContext.post_handshake_auth
以及 ssl.SSLSocket.verify_client_post_handshake()
來啟用並初始化 TLS 1.3 握手後驗證。
statistics
添加了 statistics.fmean()
作為 statistics.mean()
的更快速的浮點數版版本。
添加了 statistics.geometric_mean()
添加了 statistics.multimode()
用於返回最常見值的列表。
添加了 statistics.quantiles()
用於將資料或分佈劃分為多個等概率區間
添加了 statistics.NormalDist
用於建立和操縱隨機變數的正態分佈。
>>> temperature_feb = NormalDist.from_samples([4, 12, -3, 2, 7, 14])
>>> temperature_feb.mean
6.0
>>> temperature_feb.stdev
6.356099432828281
>>> temperature_feb.cdf(3) # Chance of being under 3 degrees
0.3184678262814532
>>> # Relative chance of being 7 degrees versus 10 degrees
>>> temperature_feb.pdf(7) / temperature_feb.pdf(10)
1.2039930378537762
>>> el_niño = NormalDist(4, 2.5)
>>> temperature_feb += el_niño # Add in a climate effect
>>> temperature_feb
NormalDist(mu=10.0, sigma=6.830080526611674)
>>> temperature_feb * (9/5) + 32 # Convert to Fahrenheit
NormalDist(mu=50.0, sigma=12.294144947901014)
>>> temperature_feb.samples(3) # Generate random samples
[7.672102882379219, 12.000027119750287, 4.647488369766392]
sys
添加了新的 sys.unraisablehook()
函式,可被過載以便控制如何處理“不可引發的異常”。 它會在發生了一個異常但 Python 沒有辦法處理時被呼叫。 例如,當一個析構器在垃圾回收時 (gc.collect()
) 所引發的異常。
tarfile
tarfile
模組現在對新的歸檔預設使用 modern pax (POSIX.1-2001) 格式而不再是之前的 GNU 專屬格式。 這通過標準化和可擴充套件格式的統一編碼 (UTF-8) 提升了跨平臺可移植性,還提供了其他一些益處。
threading
添加了新的 threading.excepthook()
函式用來處理未捕獲的 threading.Thread.run()
異常。 它可被過載以便控制如何處理未捕獲的 threading.Thread.run()
異常。
添加了新的 threading.get_native_id()
函式以及 threading.Thread
類的 native_id
屬性。 它們會返回核心所分配給當前執行緒的原生整數執行緒 ID。 此特性僅在特定平臺上可用,參見 get_native_id
瞭解詳情。
tokenize
當提供不帶末尾新行的輸入時,tokenize
模組現在會隱式地新增 NEWLINE
形符。 此行為現在已與 C 詞法分析器的內部行為相匹配。
tkinter
在 tkinter.Spinbox
中添加了方法 selection_from()
, selection_present()
, selection_range()
和 selection_to()
。
在 tkinter.Canvas
類中添加了方法 moveto()
。
tkinter.PhotoImage
類現在具有 transparency_get()
和 transparency_set()
方法。
time
為 macOS 10.12 添加了新的時鐘 CLOCK_UPTIME_RAW
。
typing
typing
模組加入了一些新特性:
-
一個帶有鍵專屬型別的字典型別。 參見 PEP 589 和
typing.TypedDict
。 TypedDict 只使用字串作為鍵。 預設情況下每個鍵都要求提供。 指定 "total=False" 以允許鍵作為可選項:class Location(TypedDict, total=False): lat_long: tuple grid_square: str xy_coordinate: tuple
-
Literal 型別。 參見 PEP 586 和
typing.Literal
。 Literal 型別指明一個形參或返回值被限定為一個或多個特定的字面值:def get_status(port: int) -> Literal['connected', 'disconnected']: ...
-
"Final" 變數、函式、方法和類。 參見 PEP 591,
typing.Final
和typing.final()
。 final 限定符會指示靜態型別檢查器限制進行子類化、過載或重新賦值:pi: Final[float] = 3.1415926536
-
協議定義。 參見 PEP 544,
typing.Protocol
和typing.runtime_checkable()
。 簡單的 ABC 例如typing.SupportsInt
現在是Protocol
的子類。 -
新的協議類
typing.SupportsIndex
。 -
新的函式
typing.get_origin()
和typing.get_args()
。
unicodedata
unicodedata
模組現在已升級為使用 Unicode 12.1.0 釋出版。
新的函式 is_normalized()
可被用來驗證字串是否為特定正規形式,通常會比實際進行字串正規化要快得多。
unittest
添加了 AsyncMock
以支援非同步版本的 Mock
。 同時也添加了相應的斷言函式用於測試。
unittest 添加了 addModuleCleanup()
和 addClassCleanup()
以支援對 setUpModule()
和 setUpClass()
進行清理。
一些模擬斷言函式現在也會在失敗時列印一個實際呼叫列表。
unittest
模組已支援通過 unittest.IsolatedAsyncioTestCase
來使用協程作為測試用例。
import unittest
class TestRequest(unittest.IsolatedAsyncioTestCase):
async def asyncSetUp(self):
self.connection = await AsyncConnection()
async def test_get(self):
response = await self.connection.get("https://example.com")
self.assertEqual(response.status_code, 200)
async def asyncTearDown(self):
await self.connection.close()
if __name__ == "__main__":
unittest.main()
venv
現在 venv
在所有平臺上都會包含 Activate.ps1
指令碼用於在 PowerShell Core 6.1 下啟用虛擬環境。
weakref
由 weakref.proxy()
返回的代理物件現在除其他算術運算子外也支援矩陣乘法運算子 @
和 @=
。
xml
作為對 DTD 和外部實體檢索的緩解,在預設情況下 xml.dom.minidom
和 xml.sax
模組不再處理外部實體。
xml.etree.ElementTree
模組中的 .find*()
方法支援萬用字元搜尋例如 {*}tag
,此搜尋會忽略名稱空間以及返回給定名稱空間中所有標籤的 {namespace}*
。
xml.etree.ElementTree
模組提供了實現 C14N 2.0 的新函式 –xml.etree.ElementTree.canonicalize()
。
xml.etree.ElementTree.XMLParser
的目標物件可通過新的回撥方法 start_ns()
和 end_ns()
來接受名稱空間宣告事件。 此外,xml.etree.ElementTree.TreeBuilder
目標可被配置為處理有關注釋和處理指令事件以將它們包含在所生成的樹當中。
效能優化
-
subprocess
模組現在能在某些情況下使用os.posix_spawn()
函式以獲得更好的效能。 目前,它的使用僅限 macOS 和 Linux(使用 glibc 2.24 或更新版本),並要求滿足以下條件:- close_fds 為假值;
- preexec_fn, pass_fds, cwd 和 start_new_session 形參未設定;
- executable 路徑包含一個目錄。
(由 Joannah Nanjekye 和 Victor Stinner 在 bpo-35537 中貢獻。)
-
shutil.copyfile()
,shutil.copy()
,shutil.copy2()
,shutil.copytree()
和shutil.move()
在 Linux 和 macOS 上會使用平臺專屬的 "fast-copy" 系統呼叫以提高效率。 "fast-copy" 意味著拷貝操作發生於核心中,從而避免在進行 "outfd.write(infd.read())
" 等操作時使用 Python 中的使用者空間緩衝區。 在 Windows 上shutil.copyfile()
會使用更大的預設緩衝區(1 MiB 而不是 16 KiB)並且使用基於memoryview()
的shutil.copyfileobj()
版本。 在同一分割槽內拷貝一個 512 MiB 檔案的速度提升在 Linux 上約為 +26%,在 macOS 上為 +50%,在 Windows 上為 +40%。 此外還將消耗更少的 CPU 週期。 參見 Platform-dependent efficient copy operations 一節。 (由 Giampaolo Rodolà 在 bpo-33671 中貢獻。) -
shutil.copytree()
會根據其所用快取的os.stat()
值使用os.scandir()
函式及所有拷貝函式。 拷貝一個包含 8000 檔案的目錄的速度提升在 Linux 上約為 +9%,在 Windows 上為 +20%,對於 Windows SMB 共享目錄則為 +30%。 此外os.stat()
系統呼叫的次數也減少了 38%,使得shutil.copytree()
在網路檔案系統上會特別快速。 (由Giampaolo Rodolà 在 bpo-33695 中貢獻。) -
pickle
模組使用的預設協議現在為 Protocol 4,最早在 Python 3.4 中被引入。 它提供了比自 Python 3.0 起可用的 Protocol 3 更好的效能和更小的資料尺寸。 -
Removed one
Py_ssize_t
member fromPyGC_Head
. All GC tracked objects (e.g. tuple, list, dict) size is reduced 4 or 8 bytes. (Contributed by Inada Naoki in bpo-33597.) -
uuid.UUID
now uses__slots__
to reduce its memory footprint. (Contributed by Wouter Bolsterlee and Tal Einat in bpo-30977) -
operator.itemgetter()
的效能提升了 33%。 優化了引數處理,併為常見的在元組中單個非負整數索引的情況新增了一條快速路徑(這是標準庫中的典型用例)。 (由 Raymond Hettinger 在 bpo-35664 中貢獻。 -
加快了在
collections.namedtuple()
中的欄位查詢。 它們現在的速度快了兩倍以上,成為 Python 中最快的例項變數查詢形式。 (由 Raymond Hettinger, Pablo Galindo 和 Joe Jevnik, Serhiy Storchaka 在 bpo-32492 中貢獻。) -
如果輸入的可迭代物件的長度已知 (即輸入物件實現了
__len__
),list
構造器不會過度分配內部項緩衝區。 這使得所建立的列表資源佔用平均減少了 12%。 (由 Raymond Hettinger 和 Pablo Galindo 在 bpo-33234 中貢獻。) -
類變數寫入速度加倍。 當一個非冗餘屬性被更新時,之前存在一個更新 slots 的非必要呼叫。 (由 Stefan Behnel, Pablo Galindo Salgado, Raymond Hettinger, Neil Schemenauer, 和 Serhiy Storchaka 在 bpo-36012 中貢獻。)
-
減少了傳遞給許多內建函式和方法的引數轉換的開銷。 這使得某些簡單內建函式和方法的速度提升了 20--50%。 (由 Serhiy Storchaka 在 bpo-23867, bpo-35582 和 bpo-36127 中貢獻。)
-
LOAD_GLOBAL
指令現在會使用新的 "per opcode cache" 機制。 它的速度現在提升了大約 40%。 (由 Yury Selivanov 和 Inada Naoki 在 bpo-26219 中貢獻。)
構建和 C API 的改變
-
預設的
sys.abiflags
成為一個空字串:pymalloc 的m
旗標不再有意義(無論是否啟用 pymalloc 構建都是相容 ABI 的)因此已被移除。 (由 Victor Stinner 在 bpo-36707 中貢獻。)改變的例子:
- 只會安裝
python3.8
程式,不再有python3.8m
程式。 - 只會安裝
python3.8-config
指令碼,不再有python3.8m-config
指令碼。 m
旗標已經從動態庫檔名字尾中移除:包括標準庫中的擴充套件模組以及第三方包所產生和安裝的模組例如從 PyPI 下載的模組。 以 Linux 為例,Python 3.7 的字尾.cpython-37m-x86_64-linux-gnu.so
在 Python 3.8 中改為.cpython-38-x86_64-linux-gnu.so
。
- 只會安裝
-
重新組織了所有標頭檔案以更好地區分不同種類的 API:
Include/*.h
應為可移植的公有穩定版 C API。Include/cpython/*.h
應為 CPython 專屬的不穩定版 C API;公有 API,部分私有 API 附加_Py
or_PY
字首。Include/internal/*.h
應為 CPython 特別專屬的私有內部 C API。 此 API 不具備向下相容保證並且不應在 CPython 以外被使用。 它們的公開僅適用於特別限定的需求例如偵錯程式和效能分析等必須直接訪問 CPython 內部資料而不通過呼叫函式的應用。 此 API 現在是通過make install
安裝的。
(由 Victor Stinner 在 bpo-35134 和 bpo-35081 中貢獻,相關工作由 Eric Snow 在 Python 3.7 中發起。)
-
某些巨集已被轉換為靜態行內函數:形參型別和返回型別定義良好,它們不再會有與巨集相關的問題,變數具有區域性作用域。 例如:
Py_INCREF()
,Py_DECREF()
Py_XINCREF()
,Py_XDECREF()
PyObject_INIT()
,PyObject_INIT_VAR()
- 私有函式:
_PyObject_GC_TRACK()
,_PyObject_GC_UNTRACK()
,_Py_Dealloc()
(由 Victor Stinner 在 bpo-35059 中貢獻。)
-
PyByteArray_Init()
和PyByteArray_Fini()
函式已被移除。 它們自 Python 2.7.4 和 Python 3.2.0 起就沒有任何用處,被排除在受限 API (穩定版 ABI) 之外,並且未被寫入文件。 (由 Victor Stinner 在 bpo-35713 中貢獻。) -
PyExceptionClass_Name()
的結果型別現在是const char *
而非char *
。 (由 Serhiy Storchaka 在 bpo-33818 中貢獻。) -
Modules/Setup.dist
與Modules/Setup
兩者的共存已被移除。 之前在更新 CPython 原始碼樹時,開發者必須手動拷貝Modules/Setup.dist
(在原始碼樹內) 到Modules/Setup
(在構建樹內) 以反映上游的任何改變。 舊特性對打包者來說有一點益處,但代價是對追蹤 CPython 開發程序的開發者造成經常性的麻煩,因為忘記拷貝該檔案可能導致構建失敗。現在構建系統總是會從原始碼樹內的
Modules/Setup
讀取資料。 建議希望定製該檔案的開發者在 CPython 的一個 git 分叉或補丁檔案中維護他們的更改,就如他們對原始碼樹做任何其他改變時一樣。(由 Antoine Pitrou 在 bpo-32430 中貢獻。)
-
將 Python 數字轉換為 C 整型的函式例如
PyLong_AsLong()
以及帶有'i'
之類整型轉換格式單元的引數解析函式例如PyArg_ParseTuple()
現在如果可能將會使用__index__()
特殊方法而不是__int__()
。 對於帶有__int__()
方法但沒有__index__()
方法的物件 (例如Decimal
和Fraction
) 將會發出棄用警告。 對於實現了__index__()
的物件PyNumber_Check()
現在將返回1
。PyNumber_Long()
,PyNumber_Float()
和PyFloat_AsDouble()
現在如果可能也將會使用__index__()
方法。 (由 Serhiy Storchaka 在 bpo-36048 和 bpo-20092 中貢獻。) -
堆分配型別物件現在將增加它們在
PyObject_Init()
(及其對應的巨集PyObject_INIT
) 中的引用計數而不是在PyType_GenericAlloc()
中。 修改例項分配或中止分配的型別可能需要進行調整。 (由 Elizondo 在 bpo-35810 中貢獻。) -
新增函式
PyCode_NewWithPosOnlyArgs()
允許建立程式碼物件例如PyCode_New()
,但帶有一個額外的 posonlyargcount 形參以指明僅限位置引數的數量。 (由 Pablo Galindo 在 bpo-37221 中貢獻。) -
Py_SetPath()
現在會將sys.executable
設為程式完整路徑 (Py_GetProgramFullPath()
) 而不是程式名稱 (Py_GetProgramName()
)。 (由 Victor Stinner 在 bpo-38234 中貢獻。)
棄用
-
distutils 的
bdist_wininst
命令現在已棄用,請改用bdist_wheel
(wheel 包)。 (由 Victor Stinner 在 bpo-37481 中貢獻。) -
ElementTree
模組中的已棄用方法getchildren()
和getiterator()
現在會引發DeprecationWarning
而不是PendingDeprecationWarning
。 它們將在 Python 3.9 中被移除。 (由 Serhiy Storchaka 在 bpo-29209 中貢獻。) -
將不是
concurrent.futures.ThreadPoolExecutor
例項的物件傳給asyncio.loop.set_default_executor()
已被棄用,並將在 Python 3.9 中被禁止。 (由 Elvis Pranskevichus 在 bpo-34075 中貢獻。) -
xml.dom.pulldom.DOMEventStream
,wsgiref.util.FileWrapper
和fileinput.FileInput
的__getitem__()
方法已被棄用。這些方法的實現會忽略它們的 index 形參,並改為返回下一條目。 (由 Berker Peksag 在 bpo-9372 中貢獻。)
-
typing.NamedTuple
類已棄用了_field_types
屬性而改用具有同樣資訊的__annotations__
屬性。 (由 Raymond Hettinger 在 bpo-36320 中貢獻。) -
ast
類Num
,Str
,Bytes
,NameConstant
和Ellipsis
被視為已棄用並將在未來的 Python 版本中被移除。 應當改用Constant
。 (由 Serhiy Storchaka 在 bpo-32892 中貢獻。) -
ast.NodeVisitor
的方法visit_Num()
,visit_Str()
,visit_Bytes()
,visit_NameConstant()
和visit_Ellipsis()
現在已被棄用,並且在未來的 Python 版本中將不再被呼叫。 新增visit_Constant()
方法來處理所有常量節點。 (由 Serhiy Storchaka 在 bpo-36917 中貢獻。) -
gettext
模組中的下列函式和方法已被棄用:lgettext()
,ldgettext()
,lngettext()
和ldngettext()
。 它們返回已編碼的位元組串,如果轉換後的字串存在編碼問題你將可能遭遇預期之外的異常。 更好的做法是使用 Python 3 中返回 Unicode 字串的操作作為替代。 前面的函式都早已不宜使用。函式
bind_textdomain_codeset()
,方法output_charset()
和set_output_charset()
,以及函式translation()
和install()
的 codeset 形參也憶被棄用,因為它們僅適用於l*gettext()
函式。 (由 Serhiy Storchaka 在 bpo-33710 中貢獻。) -
threading.Thread
的isAlive()
方法已棄用。 (由 Dong-hee Na 在 bpo-35283 中貢獻。) -
許多接受整數引數的內建和擴充套件模組的函式現在將對傳入
Decimal
,Fraction
以及任何其他可被轉換為整數但會丟失精度(即具有__int__()
方法但沒有__index__()
方法)的物件發出棄用警告。 在未來的版本中則將報錯。 (由 Serhiy Storchaka 在 bpo-36048 中貢獻。) -
以下引數作為關鍵字引數傳遞的方式已被棄用:
functools.partialmethod()
,weakref.finalize()
,profile.Profile.runcall()
,cProfile.Profile.runcall()
,bdb.Bdb.runcall()
,trace.Trace.runfunc()
與curses.wrapper()
中的 func。unittest.TestCase.addCleanup()
中的 function。concurrent.futures.ThreadPoolExecutor
和concurrent.futures.ProcessPoolExecutor
的submit()
方法中的 fn。contextlib.ExitStack.callback()
,contextlib.AsyncExitStack.callback()
和contextlib.AsyncExitStack.push_async_callback()
中的 callback。multiprocessing.managers.Server
和multiprocessing.managers.SharedMemoryServer
的create()
方法中的 c 和 typeid。weakref.finalize()
中的 obj。
在未來版本的 Python 中它們將成為 僅限位置引數。 (由 Serhiy Storchaka 在 bpo-36492 中貢獻。)
API 與特性的移除
下列特性與 API 已從 Python 3.8 中移除:
macpath
模組,在 Python 3.7 中棄用,現已被移除。- 函式
platform.popen()
已被移除,它自 Python 3.3 起就已被棄用:請改用os.popen()
。 - 函式
time.clock()
已被移除,它自 Python 3.3 起就已被棄用:請根據具體需求改用time.perf_counter()
或time.process_time()
以獲得具有良好定義的行為。 pyvenv
指令碼已被移除,推薦改用python3.8 -m venv
來幫助消除容易混淆pyvenv
指令碼所關聯的 Python 直譯器這一問題。parse_qs
,parse_qsl
和escape
已從cgi
模組中被移除。 這些函式自 Python 3.2 或更早就已被棄用。 它們應改為從urllib.parse
和html
模組匯入。filemode
函式已從tarfile
模組中被移除。 該函式未被寫入文件,自 Python 3.3 起就已棄用。XMLParser
構造器不再接受 html 引數。 它從來沒有任何作用並在 Python 3.4 中已被棄用。 所有其他形參現在都是 僅限關鍵字引數。XMLParser
的doctype()
方法已被移除。- "unicode_internal" 編解碼器已被移除。
sqlite3
模組的Cache
和Statement
物件已不再公開給使用者。fileinput.input()
和fileinput.FileInput()
中自 Python 3.6 起就已被忽略並棄用的bufsize
關鍵字引數已被移除。- 在 Python 3.7 中棄用的函式
sys.set_coroutine_wrapper()
和sys.get_coroutine_wrapper()
已被移除。
移植到 Python 3.8
本節列出了先前描述的更改以及可能需要更改程式碼的其他錯誤修正.
Python 行為的改變
- yield 表示式(包括
yield
和yield from
子句)現在不允許在推導式和生成器表示式中使用(但for
子句最左邊的可迭代物件表示式除外)。 (由 Serhiy Storchaka 在 bpo-10544 中貢獻。) - The compiler now produces a
SyntaxWarning
when identity checks (is
andis not
) are used with certain types of literals (e.g. strings, numbers). These can often work by accident in CPython, but are not guaranteed by the language spec. The warning advises users to use equality tests (==
and!=
) instead. (Contributed by Serhiy Storchaka in bpo-34850.) - CPython 直譯器在某些情況下可以忽略異常。 在 Python 3.8 中這種情況會更少發生。 特別地,從型別字典獲取屬性時引發的異常不會再被忽略。 (由 Serhiy Storchaka 在 bpo-35459 中貢獻。)
- 從內建型別
bool
,int
,float
,complex
和標準庫的一些類中移除了__str__
實現。 它們現在會從object
繼承__str__()
。 作為結果,在這些類的子類中定義__repr__()
方法將會影響它們的字串表示。 (由 Serhiy Storchaka 在 bpo-36793 中貢獻。) - 在 AIX 上,
sys.platform
將不再包含主要版本號。 它將總是'aix'
而不再是'aix3'
..'aix7'
。 由於較舊的 Python 版本會包含該版本號,因此推薦總是使用sys.platform.startswith('aix')
。 (由 M. Felt 在 bpo-36588 中貢獻。) PyEval_AcquireLock()
andPyEval_AcquireThread()
now terminate the current thread if called while the interpreter is finalizing, making them consistent withPyEval_RestoreThread()
,Py_END_ALLOW_THREADS()
, andPyGILState_Ensure()
. If this behavior is not desired, guard the call by checking_Py_IsFinalizing()
orsys.is_finalizing()
. (Contributed by Joannah Nanjekye in bpo-36475.)
更改的Python API
- 在 Windows 上
os.getcwdb()
函式現在會使用 UTF-8 編碼格式而不是 ANSI 內碼表:請參看 PEP 529 瞭解具體原因。 該函式在 Windows 上不再被棄用。 (由 Victor Stinner 在 bpo-37412 中貢獻。) - 現在
subprocess.Popen
在某些情況下會使用os.posix_spawn()
以獲得更好的效能。 在適用於 Linux 的 Windows 子系統和 QEMU 使用者模擬器上,使用os.posix_spawn()
的Popen
構造器不會再因為“找不到程式”這樣的錯誤引發異常。 而是讓子程序失敗並返回一個非零的returncode
。 (由 Joannah Nanjekye 和 Victor Stinner 在 bpo-35537 中貢獻。) - The preexec_fn argument of *
subprocess.Popen
is no longer compatible with subinterpreters. The use of the parameter in a subinterpreter now raisesRuntimeError
. (Contributed by Eric Snow in bpo-34651, modified by Christian Heimes in bpo-37951.) - The
imap.IMAP4.logout()
method no longer ignores silently arbitrary exceptions. (Contributed by Victor Stinner in bpo-36348.) - 函式
platform.popen()
已被移除,它自 Python 3.3 起就已被棄用:請改用os.popen()
。 (由 Victor Stinner 在 bpo-35345 中貢獻。) - 當傳入多模資料時
statistics.mode()
函式不會再引發異常。 它將改為返回在輸入資料中遇到的第一個模式。 (由 Raymond Hettinger 在 bpo-35892 中貢獻。) tkinter.ttk.Treeview
類的selection()
方法不再接受引數。 帶引數呼叫該方法來改變選擇在 Python 3.6 中已棄用。 請使用專門方法例如selection_set()
來改變選擇。 (由 Serhiy Storchaka 在 bpo-31508 中貢獻。)xml.dom.minidom
的writexml()
,toxml()
和toprettyxml()
方法以及xml.etree
的write()
方法現在會保留使用者指定的屬性順序。 (由 Diego Rojas 和 Raymond Hettinger 在 bpo-34160 中貢獻。)- 附帶
'r'
旗標開啟的dbm.dumb
資料庫現在將是隻讀的。 如果資料庫不存在,附帶'r'
和'w'
旗標的dbm.dumb.open()
不會再建立資料庫。 (由 Serhiy Storchaka 在 bpo-32749 中貢獻。) - 在
XMLParser
的子類中定義的doctype()
方法將不會再被呼叫,並將導致發出RuntimeWarning
而不是DeprecationWarning
。 請在目標上定義doctype()
方法來處理 XML doctype 宣告。 (由 Serhiy Storchaka 在 bpo-29209 中貢獻。) - 現在當自定義元類未在傳給
type.__new__
的名稱空間中提供__classcell__
入口時將引發RuntimeError
。 在 Python 3.6--3.7 中是則是引發DeprecationWarning
。 (由 Serhiy Storchaka 在 bpo-23722 中貢獻。) cProfile.Profile
類現在可被用作上下文管理器。 (由 Scott Sanderson 在 bpo-29235 中貢獻。)shutil.copyfile()
,shutil.copy()
,shutil.copy2()
,shutil.copytree()
和shutil.move()
會使用平臺專屬的 "fast-copy" 系統呼叫(參見 Platform-dependent efficient copy operations 一節)。shutil.copyfile()
在 Windows 上的預設緩衝區大小從 16 KiB 改為 1 MiB。PyGC_Head
結構已被完全改變。 所有接觸到該結構的程式碼都應當被重寫。 (參見 bpo-33597。)PyInterpreterState
結構已被移入 "internal" 標頭檔案 (特別是 Include/internal/pycore_pystate.h)。 不透明的PyInterpreterState
作為公有 API (和穩定版 ABI) 的一部分仍然可用。 文件指明該結構的任何欄位都不是公有的,因此我們希望沒人在使用它們。 但是,如果你確實依賴其中某一個或更多個私有欄位並且沒有其他替代選項,則請開一個 BPO 問題。 我們將盡力幫助你進行調整 (可能包括向公有 API 新增訪問器函式)。 (參見 bpo-35886。)- 現在 asyncio 任務可以被命名,具體方式是將
name
關鍵字引數傳給asyncio.create_task()
或create_task()
事件迴圈方法,或是在任務物件上呼叫set_name()
方法。 任務名稱可在asyncio.Task
的repr()
輸出中檢視,並可使用get_name()
方法來獲取。 - 現在所有平臺下的
mmap.flush()
方法都會在成功時返回None
並在錯誤時引發異常。 之前它的行為取決於具體平臺: Windows 下會在成功時返回非零值;在失敗時返回零。 Unix 下會在成功時返回零;在失敗時引發錯誤。 (由 Berker Peksag 在 bpo-2122 中貢獻。) xml.dom.minidom
和xml.sax
模組預設將不再處理外部實體。 (由 Christian Heimes 在 bpo-17239 中貢獻。)- 從只讀的
dbm
資料庫 (dbm.dumb
,dbm.gnu
或dbm.ndbm
) 刪除鍵將會引發error
(dbm.dumb.error
,dbm.gnu.error
或dbm.ndbm.error
) 而不是KeyError
。 (由 Xiang Zhang 在 bpo-33106 中貢獻。) expanduser()
on Windows now prefers theUSERPROFILE
environment variable and does not useHOME
, which is not normally set for regular user accounts. (Contributed by Anthony Sottile in bpo-36264.)- The exception
asyncio.CancelledError
now inherits fromBaseException
rather than aException
. (Contributed by Yury Selivanov in bpo-13528.) - DLL dependencies for extension modules and DLLs loaded with
ctypes
on Windows are now resolved more securely. Only the system paths, the directory containing the DLL or PYD file, and directories added withadd_dll_directory()
are searched for load-time dependencies. Specifically,PATH
and the current working directory are no longer used, and modifications to these will no longer have any effect on normal DLL resolution. If your application relies on these mechanisms, you should check foradd_dll_directory()
and if it exists, use it to add your DLLs directory while loading your library. Note that Windows 7 users will need to ensure that Windows Update KB2533625 has been installed (this is also verified by the installer). (Contributed by Steve Dower in bpo-36085.) - 關聯到 pgen 的標頭檔案和函式在其被純 Python 實現取代後已被移除。 (由 Pablo Galindo 在 bpo-36623 中貢獻。)
types.CodeType
在構造器的第二個位置新增了一個形參 (posonlyargcount) 以支援在 PEP 570 中定義的僅限位置引數。 第一個引數 (argcount) 現在表示位置引數的總數量 (包括僅限位置引數)。types.CodeType
中新增的replace()
方法可用於讓程式碼支援 future 特性。
C API 中的改變
-
The
PyCompilerFlags
structure got a new cf_feature_version field. It should be initialized toPY_MINOR_VERSION
. The field is ignored by default, and is used if and only ifPyCF_ONLY_AST
flag is set in cf_flags. (Contributed by Guido van Rossum in bpo-35766.) -
PyEval_ReInitThreads()
函式已從 C API 中移除。 它不應當被顯式地呼叫;請改用PyOS_AfterFork_Child()
。 (由 Victor Stinner 在 bpo-36728 中貢獻。) -
在 Unix 上,C 擴充套件不會再被連結到 libpython,但 Android 和 Cygwin 例外。 當 Python 被嵌入時,
libpython
不可使用RTLD_LOCAL
載入,而要改用RTLD_GLOBAL
。 之前使用RTLD_LOCAL
已經不可能載入未連結到libpython
的 C 擴充套件了,例如通過Modules/Setup
的*shared*
部分構建的標準庫 C 擴充套件。 (由 Victor Stinner 在 bpo-21536 中貢獻。) -
在解析或構建值時(例如
PyArg_ParseTuple()
,Py_BuildValue()
,PyObject_CallFunction()
等等)使用形如#
的格式而不定義PY_SSIZE_T_CLEAN
現在將會引發DeprecationWarning
。 它將在 3.10 或 4.0 中被移除。 請參閱 語句解釋及變數編譯 瞭解詳情。 (由 Inada Naoki 在 bpo-36381 中貢獻。) -
堆分配型別的例項(例如使用
PyType_FromSpec()
建立的例項)會儲存一個對其型別物件的引用。 提升這些型別物件引用計數的操作已從PyType_GenericAlloc()
移至更低層級的函式PyObject_Init()
和PyObject_INIT()
。 這使用通過This makes types created throughPyType_FromSpec()
所建立型別的行為與管理程式碼中的其他類保持一致。靜態分配型別將不受影響。
在大部分情況下,這應該都不會有附帶影響。 但是,在分配例項後手動提升引用計數的型別(也許是為了繞過漏洞)現在可能永遠不會被銷燬。 要避免這種情況,這些類需要在例項撤銷分配期間在型別物件上呼叫 Py_DECREF。
要正確地將這些型別移植到 3.8,請應用以下修改:
-
在分配例項之後在型別物件上移除
Py_INCREF
—— 如果有的話。 這可以發生在呼叫PyObject_New()
,PyObject_NewVar()
,PyObject_GC_New()
,PyObject_GC_NewVar()
或任何其他使用PyObject_Init()
或PyObject_INIT()
的自定義分配器之後。示例:
static foo_struct * foo_new(PyObject *type) { foo_struct *foo = PyObject_GC_New(foo_struct, (PyTypeObject *) type); if (foo == NULL) return NULL; #if PY_VERSION_HEX < 0x03080000 // Workaround for Python issue 35810; no longer necessary in Python 3.8 PY_INCREF(type) #endif return foo; }
確保所有堆分配型別的自定義
tp_dealloc
函式會減少型別的引用計數。static void foo_dealloc(foo_struct *instance) { PyObject *type = Py_TYPE(instance); PyObject_GC_Del(instance); #if PY_VERSION_HEX >= 0x03080000 // This was not needed before Python 3.8 (Python issue 35810) Py_DECREF(type); #endif }
-
-
Py_DEPRECATED()
巨集已經針對 MSVC 實現。 這個巨集現在必須放在符號名稱之前。示例:
Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void);
-
直譯器將不再假裝支援跨釋出版本的擴充套件型別二進位制相容性。 由第三方擴充套件模組所匯出的
PyTypeObject
應該具有當前 Python 版本所要求的所有空位,包括tp_finalize
(Py_TPFLAGS_HAVE_FINALIZE
不會再在讀取tp_finalize
之前被檢查)。(由 Antoine Pitrou 在 bpo-32388 中貢獻。)
-
PyCode_New()
在第二個位置添加了新的形參 (posonlyargcount) 以支援 PEP 570,指明僅限位置引數的數量。 -
函式
PyNode_AddChild()
和PyParser_AddToken()
現在接受兩個額外的int
引數 end_lineno 和 end_col_offset。 -
The
libpython38.a
file to allow MinGW tools to link directly againstpython38.dll
is no longer included in the regular Windows distribution. If you require this file, it may be generated with thegendef
anddlltool
tools, which are part of the MinGW binutils package:gendef python38.dll > tmp.def dlltool --dllname python38.dll --def tmp.def --output-lib libpython38.a
已安裝的
pythonXY.dll
所在位置將取決於安裝選項以及 Windows 的版本和語言。 請參閱 在Windows上使用 Python 瞭解更多資訊。 該結果庫應當放在與pythonXY.lib
相同的目錄下,這通常是你的 Python 安裝路徑下的libs
目錄。
CPython 位元組碼的改變
-
直譯器迴圈已通過將塊堆疊展開邏輯移入編譯器獲得了簡化。 編譯器現在會發出顯式指令來調整值堆疊併為
break
,continue
和return
呼叫清除程式碼。移除了操作碼
BREAK_LOOP
,CONTINUE_LOOP
,SETUP_LOOP
和SETUP_EXCEPT
。 添加了新的操作碼ROT_FOUR
,BEGIN_FINALLY
,CALL_FINALLY
和POP_FINALLY
。 修改了END_FINALLY
和WITH_CLEANUP_START
的行為。 -
添加了新的操作碼
END_ASYNC_FOR
用於處理當等待async for
迴圈的下一項時引發的異常。 -
MAP_ADD
現在會預期值為棧的第一個元素而鍵為第二個元素。 作出此改變以使得字典推導式能如 PEP 572 所提議的那樣,鍵總是會在值之前被求值。
演示和工具
- 添加了一個檢測指令碼用於對訪問變數的不同方式進行計時:
Tools/scripts/var_access_benchmark.py
。