[解決済み】Python 3.5の型ヒントは何ですか?
質問
Python 3.5で最も話題になった機能の1つが タイプヒント .
の例です。 タイプヒント に記載されています。 この記事 と この一件 また、タイプヒントを責任を持って使用するように言及しています。どなたか、これらのヒントについて、またどのような場合に使用し、どのような場合に使用しないかについて、詳しく説明していただけませんか?
どのように解決するのですか?
を読むことをお勧めします。 PEP 483 と PEP 484 と視聴 本プレゼンテーション によって グイドー タイプヒンティングについて。
一言で言えば : タイプヒンティングは文字通り、その言葉の通りの意味です。使用しているオブジェクトの型をヒントにするのです。 .
によるものです。 ダイナミック Pythonの性質上 型の推論またはチェック を使用することは特に困難です。この事実は、開発者が書いていないコードで何が起こっているかを正確に理解することを難しくし、最も重要なことは、多くのIDEで見られる型チェックツール( PyCharm と PyDev が思い浮かびますが、オブジェクトがどのようなタイプであるかのインジケータを持っていないという事実のために、制限されています。その結果、型を推測することに頼ることになり、(プレゼンテーションで言及されたように)成功率は50%程度です。
タイプヒンティングのプレゼンテーションから2つの重要なスライドを紹介します。
なぜタイプヒントなのか?
- タイプチェッカーを支援します。 オブジェクトにどのような型を持たせたいかをヒントにすることで、例えば期待されていない型のオブジェクトを渡している場合、タイプチェッカーは簡単にそれを検出することができます。
-
ドキュメント作成に役立ちます。
あなたのコードを見る第三者は、どこで何が期待されているのか、つまり、それらを得ることなくそれを使用する方法を知ることができます。
TypeErrors
. -
IDEがより正確で堅牢なツールを開発するのを支援します。
開発環境は、オブジェクトの型がわかっている場合、適切なメソッドを提案するのに適しています。IDE を使っている人は、このような経験をしたことがあるでしょう。
.
と、オブジェクトに定義されていないメソッドや属性がポップアップ表示されることがあります。
なぜ静的型チェッカーを使うのですか?
- バグの早期発見 : これは自明のことだと思います。
- プロジェクトが大きくなればなるほど、必要になる : 繰り返しになりますが、理にかなっています。静的言語には、堅牢性と制御性があります。 動的言語にはないものです。アプリケーションが大きく複雑になればなるほど、(動的言語にはない)コントロールと予測可能性が高まります。 動作の面で)必要です。
- 大規模なチームでは、すでに静的解析を実施している : これは最初の2点を検証しているのでしょう。
この小さな紹介の締めくくりとして : これは 任意 この機能は、静的型付けの利点を享受するために導入されたと私は理解しています。
あなたは一般的に しない を気にする必要はありませんし 間違いなく を使う必要はありません(特に、Pythonを補助的なスクリプト言語として使う場合)。として、大規模なプロジェクトを開発する際に役立つはずです。 必要な堅牢性、制御、追加のデバッグ機能を提供します。 .
mypyを使ったタイプヒンティング :
この答えをより完全なものにするために、ちょっとしたデモンストレーションが適していると思います。私は、以下のものを使用します。
mypy
PEPで紹介されているType Hintsのインスピレーションとなったライブラリです。これは主に、この問題にぶつかり、何から始めたらいいのか悩んでいる人のために書かれたものです。
その前に、以下のことを再確認しておきます。 PEP 484 を強制するものではなく、単に関数 のアノテーションとガイドラインを提案しています。 なんと の型チェックを行うことができます/行う必要があります。関数にアノテーションを付けて Pythonはアノテーションを使用しないので、アノテーションがあってもスクリプトは実行されます。
とにかく、PEPに書かれているように、型のヒンティングは一般的に3つの形式を取るべきです。
- 関数アノテーション( PEP 3107 ).
- ビルトイン/ユーザーモジュール用のスタブファイル。
-
特別
# type: type
というコメントがあり、最初の2つの形式を補完する。(参照 変数アノテーションとは何ですか? のPython 3.6アップデートのため。# type: type
のコメント)
さらに、タイプヒントを併用することで、新しい
typing
モジュールで導入された
Py3.5
. その中で、多くの(追加の)
ABC
(抽象ベースクラス)が定義されており、静的チェックに使用するヘルパー関数やデコレーターも定義されています。のほとんどのABCは
collections.abc
が含まれますが、その中に
ジェネリック
を定義することで)購読できるようになります。
__getitem__()
メソッド) を使用します。
これらについてのより詳細な解説に興味のある方は
mypy documentation
は、非常にうまく書かれており、そのチェッカーの機能を実演/説明するコードサンプルが多数掲載されているので、一読の価値があります。
関数のアノテーションと特別なコメント。
まず、特殊なコメントを使用した場合の動作について、いくつか観察してみると面白い。特別な
# type: type
コメント
は、変数の代入の際に、オブジェクトの型が直接推定できない場合に、その型を示すために追加することができます。単純な代入は
一般的に容易に推測できますが、リスト(内容に関して)のように推測できないものもあります。
注
の任意の派生物を使用したい場合
コンテナ
で、そのコンテナの内容を指定する必要があります。
必須
を使用します。
ジェネリック
の型は
typing
モジュールを使用します。
これらはインデックスをサポートしています。
# Generic List, supports indexing.
from typing import List
# In this case, the type is easily inferred as type: int.
i = 0
# Even though the type can be inferred as of type list
# there is no way to know the contents of this list.
# By using type: List[str] we indicate we want to use a list of strings.
a = [] # type: List[str]
# Appending an int to our list
# is statically not correct.
a.append(i)
# Appending a string is fine.
a.append("i")
print(a) # [0, 'i']
これらのコマンドをファイルに追加し、インタープリタで実行すると、すべてがうまく動作して
print(a)
を印刷するだけです。
リストの内容
a
. その
# type
のコメントは破棄されました。
追加的な意味を持たないプレーンなコメントとして扱われる
.
これを
mypy
一方、以下のようなレスポンスが得られます。
(Python3)jimmi@jim: mypy typeHintsCode.py
typesInline.py:14: error: Argument 1 to "append" of "list" has incompatible type "int"; expected "str"
のリストであることを示す。
str
オブジェクトを含むことはできません。
int
これは、静的に言えば、健全なことです。これは、静的に見れば問題ありません。
a
を追加するだけです。
str
オブジェクトの内容の型を変えるか、あるいは
a
で直感的に実行される)。
List[Any]
の後に
Any
からインポートされました。
typing
).
関数アノテーションは、以下のような形式で追加されます。
param_name : type
は関数シグネチャの各パラメータの後に、 戻り値の型を指定するために
-> type
アノテーションはすべて、関数終了コロンの前にある
__annotations__
属性が、便利な辞書形式で用意されています。些細な例を挙げます。
typing
モジュール)。
def annotated(x: int, y: str) -> bool:
return x < y
は
annotated.__annotations__
属性は以下の値を持つようになりました。
{'y': <class 'str'>, 'return': <class 'bool'>, 'x': <class 'int'>}
もし私たちがまったくの初心者であったり、Python 2.7 の概念に慣れていて、結果として
TypeError
の比較に潜んでいる
annotated
であれば、別の静的チェックを行うことで、エラーをキャッチし、手間を省くことができます。
(Python3)jimmi@jim: mypy typeHintsCode.py
typeFunction.py: note: In function "annotated":
typeFunction.py:2: error: Unsupported operand types for > ("str" and "int")
中でも、無効な引数で関数を呼び出すと、それも捕捉されます。
annotated(20, 20)
# mypy complains:
typeHintsCode.py:4: error: Argument 2 to "annotated" has incompatible type "int"; expected "str"
これらは基本的にあらゆるユースケースに拡張でき、キャッチされるエラーは基本的な呼び出しや操作よりもさらに拡張できる。検出されるエラーの種類は
今回は、その可能性をほんの少し紹介しただけです。の中を覗いてみてください。
typing
モジュールは
PEPs または
mypy
のドキュメントを参照すると、提供される機能についてより包括的なアイデアを得ることができます。
スタブファイル
スタブファイルは、相互に排他的でない2つの異なるケースで使用することができます。
- 関数のシグネチャを直接変更したくないモジュールをタイプチェックする必要がある場合。
- モジュールを書いてタイプチェックをしたいが、さらにアノテーションとコンテンツを分離したい。
どのようなスタブファイル(拡張子が
.pyi
は、あなたが作ろうとしている/使おうとしているモジュールの注釈付きインターフェイスです。その中には
型チェックをしたい関数のシグネチャと、その関数の本体を破棄したものです。これを理解するために、一組の
という名前のモジュールに含まれる3つのランダムな関数の
randfunc.py
:
def message(s):
print(s)
def alterContents(myIterable):
return [i for i in myIterable if i % 2 == 0]
def combine(messageFunc, itFunc):
messageFunc("Printing the Iterable")
a = alterContents(range(1, 20))
return set(a)
スタブファイルを作成することができます
randfunc.pyi
その中で、もしそうしたいのであれば、いくつかの制限を設けることができます。欠点は
スタブなしでソースを見た人は、何がどうなっているのかを理解するための注釈を得ることはできないでしょう。
が渡される。
とにかく、スタブファイルの構造はとても単純です。空のボディを持つすべての関数定義を追加する (
pass
を充填し
アノテーションを追加してください。ここでは、以下のものだけを扱うとします。
int
の型をコンテナに使用します。
# Stub for randfucn.py
from typing import Iterable, List, Set, Callable
def message(s: str) -> None: pass
def alterContents(myIterable: Iterable[int])-> List[int]: pass
def combine(
messageFunc: Callable[[str], Any],
itFunc: Callable[[Iterable[int]], List[int]]
)-> Set[int]: pass
は
combine
この関数は、アノテーションを別のファイルで使用したい理由を示しています。
コードと可読性を低下させます(Pythonの大きな欠点です)。もちろん、型のエイリアスを使うこともできますが、それは時に、より混乱させることになります。
ので、賢明に使用してください)。
これで、Pythonの型ヒントの基本的な概念に慣れたはずです。使用するタイプチェッカーが
mypy
は、徐々に多くのポップアップを見るようになるはずで、IDE の内部 (
PyCharm
などをPythonの標準モジュールとして提供しています。
今後、チェッカーや関連パッケージが見つかったら(あるいは提案されたら)、以下のリストに追加していこうと思います。
私が知っているチェッカー :
関連パッケージ/プロジェクト :
- タイプシェッド Pythonの公式リポジトリで、標準ライブラリのスタブファイルの集合を収容しています。
は
typeshed
プロジェクトは、型ヒンティングを自分のプロジェクトでどのように使用するかを見るのに最も適した場所の一つです。例として
その
__init__
のダントツ1位です。
Counter
クラス
に、対応する
.pyi
ファイルを作成します。
class Counter(Dict[_T, int], Generic[_T]):
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, Mapping: Mapping[_T, int]) -> None: ...
@overload
def __init__(self, iterable: Iterable[_T]) -> None: ...
どこ
_T = TypeVar('_T')
はジェネリッククラスを定義するために使用されます
. については
Counter
クラスは、イニシャライザーで引数を取らないか、単一の
Mapping
を任意の型から
int
または
を取る
Iterable
を任意の型に変換することができます。
お知らせ
: 一つ言い忘れていたのは
typing
モジュールが導入されたのは
暫定版
. から
PEP 411
:
暫定パッケージは、quot;安定版 (stable") に移行する前に API が変更される可能性があります。一方では、この状態は Python ディストリビューションの正式な一部であるという利点をパッケージに与えます。一方で、コア開発チームはパッケージの API の安定性に関して約束はしていないと明言しており、次のリリースでは変更される可能性があります。可能性は低いと思われますが、APIやメンテナンスに関する懸念に十分な根拠があることが証明された場合、そのようなパッケージは非推奨期間なしに標準ライブラリから削除される可能性さえあります。
削除されたり、大幅に変更されたりすることはないだろうが、わからないこともある。
**
全く別の話題ですが、タイプヒントの範囲では有効です。
PEP 526
: 変数アノテーションのシンタックス
を置き換える試みです。
# type
この構文により、ユーザーは変数の種類を単純な
varname: type
ステートメントを使用します。
参照 変数アノテーションとは何ですか? は、前述したように、これらについて少し紹介します。
関連
-
Pythonコードの可読性を向上させるツール「pycodestyle」の使い方を詳しく解説します
-
Python LeNetネットワークの説明とpytorchでの実装
-
[解決済み】ImportError: bs4という名前のモジュールがない(BeautifulSoup)
-
[解決済み] 最小限の驚き」と「変更可能なデフォルトの引数
-
[解決済み] 複数行の長い文字列を作成するためのPythonicな方法
-
[解決済み] Pythonでシングルトンを作成する
-
[解決済み] Pythonの__future__は何に使うのか、いつ、どのように使うのか、その仕組みについて
-
[解決済み】if __name__ == "__main__": は何をするのでしょうか?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
opencvとpillowを用いた顔認証システム(デモあり)
-
pythonを使ったオフィス自動化コード例
-
pythonサイクルタスクスケジューリングツール スケジュール詳解
-
python implement mysql add delete check change サンプルコード
-
[解決済み】DataFrameのコンストラクタが正しく呼び出されない!エラー
-
[解決済み】終了コード -1073741515 (0xC0000135)でプロセス終了)
-
[解決済み】TypeError: 系列を <class 'float'> に変換することができません。
-
[解決済み】TypeErrorを取得しました。エントリを持つ子テーブルの後に親テーブルを追加しようとすると、 __init__() missing 1 required positional argument: 'on_delete'
-
[解決済み】 AttributeError("'str' object has no attribute 'read'")
-
[解決済み】「OverflowError: Python int too large to convert to C long" on windows but not mac