最近見たときにおもしろいことに気付いた Python 3.3文法仕様 :
funcdef: 'def' NAME parameters ['->' test] ':' suite
Python 2にはオプションの 'arrow'ブロックはありませんでしたが、Python 3ではその意味に関する情報を見つけることができませんでした。
def f(x) -> 123:
return x
私はこれがある種の前提条件構文であるかもしれないと思いました、しかし:
x
をテストすることはできません。未定義のままです。2 < 1
)、関数の動作には影響しません。この構文に慣れた人なら誰でもそれを説明できますか?
それは 関数アノテーション です。
より詳細には、Python 2.xにはdocstringがあり、これを使ってメタデータ文字列をさまざまなタイプのオブジェクトに添付することができます。これは驚くほど便利です。Python3では、パラメータと戻り値を記述する関数にメタデータを添付できるようにすることで、機能を拡張しています。
先入観のあるユースケースはありませんが、PEPはいくつか提案しています。非常に便利なのは、パラメータに予想される型で注釈を付けることができるようにすることです。その場合、注釈を検証したり、引数を正しい型に強制したりするデコレータを書くのは簡単でしょう。もう1つは、docstringにエンコードするのではなく、パラメータ固有のドキュメントを許可することです。
これらは 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.__
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>
他の答えが述べているように、->
シンボルは関数アノテーションの一部として使われています。最近のバージョンのPython >= 3.5
では、 defined の意味があります。
PEP 3107 - 関数アノテーション 仕様を記述し、文法の変更、それらが格納されているfunc.__annotations__
の存在、それがまだユースケースであるという事実を定義します。
しかしPythonでは3.5
、 PEP 484 - Type Hints はこれに一つの意味を付けます:->
は関数が返す型を示すために使われます。これは、 注釈の既存の使用法について で説明されているように、将来のバージョンでも適用されるように思われます。
考えられる最速のスキームでは、3.6では非型ヒント注釈のサイレント非推奨、3.7では完全型非推奨、および Python 3.8での注釈の唯一の許可された使用法として型ヒントを宣言します。
(私の強調)
私が言うことができる限り、これは実際には3.6
の時点で実装されていないので、将来のバージョンにぶつかるかもしれません。
これによると、あなたが提供した例:
def f(x) -> 123:
return x
将来禁止されるでしょう(そして現在のバージョンでは混乱するでしょう)、それは次のように変更される必要があるでしょう:
def f(x) -> int:
return x
その関数f
が効果的にその型を表すint
のオブジェクトを返すようにするためです。
アノテーションはPython自身では決して使われていません。それはほとんど存在し、それらを無視します。それらを扱うのはサードパーティーのライブラリ次第です。
Pythonはそれを無視します。次のコードでは:
def f(x) -> int:
return int(x)
-> int
はf()
が整数を返すことを伝えるだけです。これはreturnアノテーションと呼ばれ、f.__annotations__['return']
としてアクセスできます。
Pythonはパラメータアノテーションもサポートしています。
def f(x: float) -> int:
return int(x)
: float
は、プログラム(およびいくつかのサードパーティのライブラリ/プログラム、たとえばpylint)を読む人に、x
はfloat
であるべきであることを伝えます。これはf.__annotations__['x']
としてアクセスされ、それ自体では意味がありません。詳細についてはドキュメントを参照してください。
https://docs.python.org/3/reference/compound_stmts.html#function-definitionshttps://www.python.org/dev/peps/pep-3107/
def function(arg)->123:
これは単に戻り値の型です。integerはどの数値を書いても構いません。
Javaのように:
public int function(int args){...}
しかし、Pythonの場合(どのように Jim Fasarakis Hilliard と言った)戻り値の型は単なるヒントですとにかく文字列のような他の型を返すために..