787

私は最近、Python 3.3 の文法仕様を調べているときに興味深いことに気付きました。

funcdef: 'def' NAME parameters ['->' test] ':' suite

オプションの「矢印」ブロックは Python 2 には存在せず、Python 3 ではその意味に関する情報を見つけることができませんでした。これは正しい Python であり、インタープリターによって受け入れられていることがわかりました。

def f(x) -> 123:
    return x

これはある種の前提条件構文かもしれないと思いましたが、

  • xまだ定義されていないため、ここでテストすることはできません。
  • 矢印の後に何を付けても (例: 2 < 1)、関数の動作には影響しません。

この構文スタイルに詳しい人は説明できますか?

4

10 に答える 10

602

関数アノテーションです。

より詳細には、Python 2.x には docstrings があり、さまざまなタイプのオブジェクトにメタデータ文字列を添付できます。これは非常に便利なので、Python 3 では、パラメータと戻り値を記述する関数にメタデータを添付できるようにすることで機能を拡張しています。

先入観のあるユース ケースはありませんが、PEP ではいくつかのユース ケースが提案されています。非常に便利な方法の 1 つは、パラメーターに予想される型の注釈を付けられるようにすることです。そうすれば、注釈を検証したり、引数を正しい型に強制したりするデコレータを簡単に作成できます。もう 1 つは、パラメータ固有のドキュメントをドキュメント文字列にエンコードする代わりに許可することです。

于 2013-01-17T13:04:57.427 に答える
476

これらは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(12,30),
      kinetic_energy.__annotations__['return'])
'5,400.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>
于 2013-02-25T17:46:19.943 に答える
120

他の回答が述べているように、->シンボルは関数注釈の一部として使用されます。ただし、より最近のバージョンの Python>= 3.5では、定義された意味があります。

PEP 3107 -- Function Annotationsは仕様を記述し、文法の変更を定義し、func.__annotations__それらが格納される存在を定義し、ユースケースがまだ未解決であるという事実を示しました。

Python では3.5PEP 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関数が type のオブジェクトを返すことを効果的に説明するためintです。

注釈は、Python 自体ではまったく使用されず、ほとんど入力され、無視されます。それらを使用するのは、サードパーティのライブラリ次第です。

于 2016-12-16T23:19:19.327 に答える
4
def f(x) -> str:
return x+4

print(f(45))

結果は49になります。

または言い換えれば、「-> str」は戻り値の型には影響しません:

print(f(45).__class__)

<class 'int'>
于 2020-11-12T21:43:05.210 に答える
0

値を期待または返すことをユーザーに伝えているだけです

funcname.__annotations__詳細を印刷します

お気に入り

def function(name:str ,age:int) -> "printing the personal details ":
    print(f"name is {name} age is {age}")

function("test",20)
print(function.__annotations__)

出力

name is test age is 20
{'name': <class 'str'>, 'age': <class 'int'>, 'return': 'printing the personal details '}

値を返しても何も表示されません。

于 2021-12-13T10:44:58.930 に答える