2026年2月9日 星期一

Python 3.14語法上的新改變 文/資深講師 吳修福

 


Python 3.14語法上的新改變

吳修福 Hugh Wu

  • 精誠資訊/恆逸教育訓練中心-資深講師
  • 技術分類:資料庫

 

 

日前Python官方(www.python.org)發佈了新的3.14正式版,除了新增及強化不少的功能之外,其中語法上的一些改變是開發者需要特別注意的,否則一旦升級至3.14之後可能會造成原先的程式碼在執行上發生問題。


Annotations相關

3.13之前可以直接利用module level的annotaions在變數上加註記,然後在同一個module中利用__annotaions__進行註記的查詢:

myvar: int = 100
print(__annotations__)

# 輸出
{'myvar': <class 'int'>}

3.14之後會引發以下的錯誤訊息:

Traceback (most recent call last):
  File ".....", line 2, in <module>
    print(__annotations__)
          ^^^^^^^^^^^^^^^
NameError: name '__annotations__' is not defined.

如果需要「應急」,可以在Python腳本/程式的第一行加上以下的敘述:

from __future__ import annotations

但是這個作法並不建議使用,未來這個功能也會被移除。


3.14之後應透過新增加的annotationlib來進行註記資訊的取得,還可以利用新的延遲評估機制註記一個不存在的型態,get_annotations在使用時可以利用具名參數format來決定輸出的格式:

from annotationlib import get_annotations, Format
import sys

myvar: Undefined = 100

m = sys.modules[__name__]

# VALUE 與之前版本的輸出格一樣,但如果註記是的不存在的型態會出錯
print(get_annotations(m,format=Format.VALUE))

# FORWARDREF 如果註記是的不存在的型態會有特殊標記
print(get_annotations(m,format=Format.FORWARDREF))
# 輸出:{'x': ForwardRef('Undefined', owner=...)}

# STRING 以字串型態呈現
print(get_annotations(m,format=Format.STRING))
# 輸出:{'x': 'Undefined'}

Template string literals

3.14新增一個以「t」為前置字元的字串,但是型態不是str。跟現有的Formatted string literals相比也不會套用格式化參數:

name = 'hugh'
s1 = f'hello {name}'
s2 = t'hello {name}'
print(type(s1), s1)
print(type(s2), s2)

# 輸出
<class 'str'> hello hugh
<class 'string.templatelib.Template'> Template(strings=('hello ', ''), interpolations=(Interpolation('hugh', 'name', None, ''),))

如同字面意義,開發者可以自行撰寫函數來處理這個「範本」。以上面這個為例,我們可以利用一個函數來將小寫的名字轉成大寫並輸出我們需要的字串:

from string.templatelib import Interpolation

def upper_case_name(template):

    parts = []
    for part in template:

    if isinstance(part, Interpolation):
        parts.append(str(part.value).upper())
    else:
        parts.append(part)

    return ''.join(parts)

name = 'hugh'
s = t'hello {name}'
print(upper_case_name(s))

# 輸出
hello HUGH

更進一步可以用來處理像是HTML、CSS、SQL…等等DOM-like內容的建立。


except與except* 處理多種例外時可以省略小括號

3.14之後撰寫except子句處理多種例外型態時可以省略小括號的使用:

try:
    .....
except AError, BError:
    .....

但是如果需要將捕捉到的例外指派給變數時仍必須如上小括號。


finally區塊中的流程控制

撰寫Python程式時不應該在finally區塊中出現return、continue、break等影響脫離finally的敘述,否則很容易影響最終的執行結果,以下面這個函數為例:

def myfunc():
    try:
        print('hello')
        result = 100
        return result
    finally:
        print('world')
        return 200

print(myfunc())

# 輸出 200

如果不考慮結果,在3.13之前都是可以「正常」執行的,所以需要開發人員更小心的進行程式碼的撰寫。3.14之後仍可以執行,但是會引發「警告」訊息:

test.py:8: SyntaxWarning: 'return' in a 'finally' block return 200

如此一來可以提醒開發人員是否使用了不恰當的訊息。但是要完全抑制這個警告訊息的話可以設置環境變數PYTHONWARNINGS:

export PYTHONWARNINGS=ignore::SyntaxWarning

或是在執行時加上-W參數:

$ python -Wignore::SyntaxWarning test.py

這樣就不會在執行時出現警告訊息了。



您可在下列課程中了解更多技巧喔!

0 意見:

張貼留言