関数アノテーションは、Pythonですでに見つかっている動作と重複しているようです。それだけでなく、それらがとる意味は決して強制されないので、PEP3107に記載されている次のいずれかに使用できます。
- タイピング情報の提供
- タイプチェック
- IDEに、関数が期待して返すタイプを表示させます
- 関数のオーバーロード/ジェネリック関数
- 外国語の橋
- 適応
- 述語論理関数
- データベースクエリマッピング
- RPCパラメータマーシャリング
- その他の情報
- パラメータと戻り値のドキュメント
または完全に異なるものですら。
ある意味で、関数アノテーションは、 Pythonのユーモアコレクションの古いジョークを思い出させます。
実際、Pythonはすでにブロック区切り文字をサポートしています。
> > if foo: #{ > foo1(); > foo2(); > foo3(); > #}
その中で
def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
...
以下よりも役立つことはありません:
# a: 'x', b: 5 + 6, c: list
def foo(a, b, c): #-> max(2, 9):
...
コメントとは異なり、次のようにコード内からアクセスできるため、関数アノテーションが必要であると主張する人もいるかもしれません。
>>> def spam(a: 'eggs') -> 'ni!':
... pass
...
>>> spam.__annotations__
{'a': 'eggs', 'return': 'ni!'}
ただし、これと同じ動作は、次のようなデコレータを使用して簡単に実現できます。
def param(**kw):
def decorator(func):
def wrap(*args):
print kw
func(*args)
return wrap
return decorator
def return_(arg):
def decorator(func):
def wrap(*args):
func(*args)
print arg
return wrap
return decorator
@param(a='eggs')
@return_('ni!')
def spam(a):
pass
spam(None)
# Output:
# -------
## {'a': 'eggs'}
## ni!
Pythonはすでにアノテーションが行うことを実行できるのに、なぜ関数アノテーションに専用の構文が必要なのですか?
編集:その意味が少し不明確であることが判明したので、私は私の質問を少し拡張するつもりです。
私はこの質問を、デコレータではなく関数の注釈について具体的に尋ねています。
@decorator
def spam():
pass
の略です
def spam():
pass
spam = decorator(spam)
およびメソッド呼び出し、ここで
self.method(param)
の略です
Class.method(self, param)
これらの2つの省略形の構文ショートカットでは、それらの意味を変えることはできません。既存の代替手段があるのに、なぜそのようなショートカットが必要なのか、私は尋ねていません。それは読みやすさの問題です。関数のアノテーションは、これら2つのショートカットとは少し異なります。
def spam() -> int:
pass
と
def spam() -> 'integer':
pass
人間と同じ意味を持つかもしれませんが、コンピュータと同じ意味を持つことはありません。プログラマーが注釈が何を定義すべきかを知っていたとしても、注釈がそれをどのように定義するかについての合意された定義はありません。さらに、注釈は機能に影響を与えないため、一貫性を保つ必要はありません。
だからここに私の改訂された質問があります:
関数アノテーションが既存の言語機能にアクセスするための変更可能で一貫性のない方法を提供するのに、なぜ専用の構文が必要なのですか?注釈の使用目的が完全に定義されているのに、注釈の使用方法に強制的な定義がないのはなぜですか(PEP 3107)。