TypeVarとNewTypeの違いは何ですか?
質問
TypeVar
そして
NewType
は関連しているように見えますが、それぞれをいつ使えばいいのか、実行時と静的時の違いは何なのか、よくわかりません。
どのように解決するのですか?
この2つの概念は、他の型に関連する概念と同じように、何の関係もありません。
要するに
TypeVar
は型シグネチャで使える変数で、同じ不特定の型を複数回参照することができるのに対して
NewType
は、ある値をそれ自身の型として扱うように型チェッカに伝えるために使われます。
型変数
単純化すると、型変数は、それがどの型であるかを正確に指定することなく、同じ型を複数回参照することができます。
定義では、単一の型変数は常に同じ値をとります。
# (This code will type check, but it won't run.)
from typing import TypeVar, Generic, List, Tuple
# Two type variables, named T and R
T = TypeVar('T')
R = TypeVar('R')
# Put in a list of Ts and get out one T
def get_one(x: List[T]) -> T: ...
# Put in a T and an R, get back an R and a T
def swap(x: T, y: R) -> Tuple[R, T]:
return y, x
# A simple generic class that holds a value of type T
class ValueHolder(Generic[T]):
def __init__(self, value: T):
self.value = value
def get(self) -> T:
return self.value
x: ValueHolder[int] = ValueHolder(123)
y: ValueHolder[str] = ValueHolder('abc')
型変数が無ければ、このように
get_one
または
ValueHolder.get
.
には他にもいくつかのオプションがあります。
TypeVar
. より多くの型を渡すことで、可能な値を制限することができます (例:
TypeVar(name, int, str)
のように)、あるいは型変数のすべての値がその型のサブタイプでなければならないように上限を与えることができます(例えば
TypeVar(name, bound=int)
).
さらに、型変数を宣言するときに、共変量、共変量、またはどちらでもないかを決めることができます。これは本質的に、サブクラスやスーパークラスが一般的な型の代わりにいつ使用できるかを決定するものです。 PEP 484 では、これらの概念について説明しています。 をより詳細に説明し、追加のリソースを参照しています。
新しいタイプ
A
NewType
は、実際に新しい型を作成したり、新しいクラスのインスタンスを作成するオーバーヘッドを心配することなく、個別の型を宣言したいときのためにあります。
タイプチェッカーでは
NewType('Name', int)
のサブクラスを作成します。
int
という名前のサブクラスを作成します。
実行時に
NewType('Name', int)
は全くクラスではなく、実際には ID 関数なので
x is NewType('Name', int)(x)
は常に真です。
from typing import NewType
UserId = NewType('UserId', int)
def get_user(x: UserId): ...
get_user(UserId(123456)) # this is fine
get_user(123456) # that's an int, not a UserId
UserId(123456) + 123456 # fine, because UserId is a subclass of int
タイプチェッカーに
UserId
はこのように見えます。
class UserId(int): pass
しかし、実行時には
UserId
は基本的にこれだけです。
def UserId(x): return x
には、それ以上のことはほとんどありません。
NewType
を実行時に使用します。Python 3.8.1 の時点では、その
の実装が追加されました。
はほぼ以下の通りです。
def NewType(name, type_):
def identity(x):
return x
identity.__name__ = name
return identity
関連
-
[解決済み] staticmethodとclassmethodの違いについて
-
[解決済み] バイトを文字列に変換する
-
[解決済み] Pythonのリストメソッドであるappendとextendの違いは何ですか?
-
[解決済み] 最小限の驚き」と「変更可能なデフォルトの引数
-
[解決済み] リストを均等な大きさの塊に分割するには?
-
[解決済み] Pythonの旧スタイルのクラスと新スタイルのクラスの違いは何ですか?
-
[解決済み] pipとcondaの違いは何ですか?
-
[解決済み】__str__と__repr__の違いは何ですか?
-
[解決済み】2つの辞書を1つの式でマージする(辞書の和をとる)には?)
-
[解決済み] 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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 2つの線分が交差しているかどうかを確認するにはどうすればよいですか?
-
[解決済み] Pythonのマルチプロセッシングプールimap_unorderedの呼び出しの進捗を表示しますか?
-
[解決済み] Pythonでコード行間にかかる時間を測定するには?
-
[解決済み] Pythonの要素別タプル演算(sumなど
-
[解決済み] python-requests モジュールからのすべてのリクエストをログに記録します。
-
[解決済み] subprocess.run()の出力を抑制またはキャプチャするには?
-
[解決済み] PyQtアプリケーションのスレッド化。QtスレッドとPythonスレッドのどちらを使うか?
-
[解決済み] Pythonの検索パスを他のソースに展開する
-
[解決済み] Pythonでファイルの読み込みと上書きをする
-
[解決済み] Pythonの辞書にあるスレッドセーフについて