天天看點

PEP3107 函數注解 Function Annotations

前言

由於PEP 3107 函數註解(Function Annotations)相關中文資料極少,本人閒而無事,決定解讀一下PEP3107。此PEP由python3.0開始提出。距離上次修改有3年矣。

起因

因爲Python2.x無對函數參數與傳回值註解之標準,一堆工具和庫爲彌補此問題應運而生。部分利用裝飾器對函數參數與傳回值進行限制。 PEP3107旨在詳述此問題,減少各位對此的錯誤了解與困惑。

基本原理

函數註解具有可選性,即可用可不用; 函數註解僅僅作用在compile-time; 函數註解僅僅是作爲一種描述,在第三方庫支援下才可以表示各種用途。 例如:
def compile(source: "something compilable",
            filename: "where the compilable thing comes from",
            mode: "is this a single statement or a suite?"):
           
對於此段函數參數註解,爲某第三方庫所用時,可能作爲對參數的描述。 又或者,有些第三方庫用註解對函數輸入輸出作類型檢測,例如:
def haul(item: Haulable, *vargs: PackAnimal) -> Distance:
           
然而,以上所述的作用必須依賴第三方庫,無第三方庫支援,註解毫無作用。

語法

def foo(a: expression, b: expression = 5):
    ...

def foo(*args: expression, **kwargs: expression):
    ...
           
註解必須爲python表達式,且放在默認值"=xxx"之前。而在函數定義之際,該註解同時被執行。例如:
>>> k = 1
>>> def c():
...     global k
...     k = 3
... 
>>> k
1
>>> def a(ll:c()):
...     pass
... 
>>> k
3
           
還有就是,函數註解冒號必須緊跟參數名,不可跟括號。
def foo((x1, y1: expression),
        (x2: expression, y2: expression)=(None, None)):
    ...
           
函數傳回值註解符號爲“->”,與參數註解相似,該表達式會在函數定義之時執行。
def sum() -> expression:
    ...
           
此外,lambda表達式不能註解。

使用註解

>>> def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
...     pass
... 
>>> foo
<function foo at 0x7fd87074fd10>
>>> dir(foo)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> foo.__annotations__
{'a': 'x', 'c': <class 'list'>, 'b': 11, 'return': 9}
           
PEP3017講,用func_annotations獲取註解。而事實上,用func.__annotations__才可獲取註解,如上。而return的值,因爲return不可以作爲參數而不產生衝突。

參考用途

  • 類型檢測
  • IDE提示
  • 函數重載
  • 與其他語言的接口
  • Adaptation?
  • 邏輯陳述函數
  • 數據庫查詢影射
  • 。。。。。。

參考文章:PEP3107 http://www.python.org/dev/peps/pep-3107/