2013-01-17 28 views
175

Python 3.3 grammar specification當我最近注意到一些有趣的事情這是正確的Python和它是由接受解釋:- > Python函數定義中的含義是什麼?</p> <pre><code>funcdef: 'def' NAME parameters ['->' test] ':' suite </code></pre> <p>可選的「箭頭」塊在Python 2缺席,我找不到關於它在Python 3含義的任何信息,事實證明:

def f(x) -> 123: 
    return x 

我認爲這可能是某種前提條件的語法,而是:

  • 我無法在這裏測試x,因爲它仍然是未定義的,
  • 無論我放在箭頭後面(例如, 2 < 1),它不會影響功能行爲。

任何人都可以習慣這個語法解釋它嗎?

回答

137

這是一個function annotation

更詳細地說,Python 2.x具有文檔字符串,它允許您將元數據字符串附加到各種類型的對象。這非常方便,因此Python 3通過允許您將元數據附加到描述其參數和返回值的函數來擴展該功能。

沒有先入爲主的用例,但PEP提出了幾個。一個非常方便的是允許你用他們預期的類型註釋參數;那麼編寫一個裝飾器來驗證註釋或將參數強制轉換爲正確的類型將很容易。另一種是允許參數特定的文檔,而不是將其編碼到文檔字符串中。

+46

這些信息可以作爲'.__ annotations__'屬性獲得。 –

+1

哇,我錯過了相當廣泛的知識領域 - 不僅返回值註釋,而且參數註釋。非常感謝你 :)。 – Krotton

+1

@Krotton不能怪你錯過它,它幾乎沒有用。我只見過一個使用它們的圖書館,而且很模糊。 – delnan

85

這些是PEP 3107中涵蓋的功能註釋。具體而言,->標記返回函數註釋。

例子:

>>> def kinetic_energy(m:'in KG', v:'in M/S')->'Joules': 
... return 1/2*m*v**2 
... 
>>> kinetic_energy.__annotations__ 
{'return': 'Joules', 'v': 'in M/S', 'm': 'in KG'} 

註解是字典,所以你可以這樣做:

>>> '{:,} {}'.format(kinetic_energy(20,3000), 
     kinetic_energy.__annotations__['return']) 
'90,000,000.0 Joules' 

你也可以有一個Python數據結構,而不是隻是一個字符串:

>>> rd={'type':float,'units':'Joules','docstring':'Given mass and velocity returns kinetic energy in Joules'} 
>>> def f()->rd: 
... pass 
>>> f.__annotations__['return']['type'] 
<class 'float'> 
>>> f.__annotations__['return']['units'] 
'Joules' 
>>> f.__annotations__['return']['docstring'] 
'Given mass and velocity returns kinetic energy in Joules' 

或者,您可以使用函數屬性來驗證調用的值:

def validate(func, locals): 
    for var, test in func.__annotations__.items(): 
     value = locals[var] 
     try: 
      pr=test.__name__+': '+test.__docstring__ 
     except AttributeError: 
      pr=test.__name__ 
     msg = '{}=={}; Test: {}'.format(var, value, pr) 
     assert test(value), msg 

def between(lo, hi): 
    def _between(x): 
      return lo <= x <= hi 
    _between.__docstring__='must be between {} and {}'.format(lo,hi)  
    return _between 

def f(x: between(3,10), y:lambda _y: isinstance(_y,int)): 
    validate(f, locals()) 
    print(x,y) 

打印

>>> f(2,2) 
AssertionError: x==2; Test: _between: must be between 3 and 10 
>>> f(3,2.1) 
AssertionError: y==2.1; Test: <lambda> 
14

作爲其他的答案所指出的,所述符號->用作功能註解的一部分。在Python >= 3.5的更新版本中,它具有定義的的含義。

PEP 3107 -- Function Annotations描述了規範,定義了語法變化,存儲它們的func.__annotations__以及它的用例仍然是開放的。

在Python 3.5雖然,PEP 484 -- Type Hints附加一個單一的含義:->用於指示函數返回的類型。它還看起來這將在未來的版本中予以強制執行,在What about existing uses of annotations描述:在3.7

最快可能的方案將引入非A型暗示的註解沉默棄用在3.6,完全棄用,並聲明類型提示作爲Python 3.8中唯一允許使用註釋的方式。

(重點煤礦)

這並沒有被實際爲3.6據我可以告訴因此它可能會碰到到將來的版本中實現。

根據這一點,比如你所提供的:

def f(x) -> 123: 
    return x 

將在未來被禁止(在目前的版本將是混亂的),那就需要更改爲:

def f(x) -> int: 
    return x 

它有效地描述該功能f返回類型爲int的對象。

Python本身沒有以任何方式使用註釋,它幾乎填充並忽略它們。第三方庫需要與他們合作。

相關問題