TypeVarとNewTypeの違いは何ですか?質問する

TypeVarとNewTypeの違いは何ですか?質問する

TypeVarそしてNewType関連しているように見えますが、それぞれをいつ使用すればよいのか、実行時と静的にどのような違いがあるのか​​がよくわかりません。

ベストアンサー1

これら 2 つの概念は、他の型関連の概念と比べてそれほど関連がありません。

つまり、 a はTypeVar型シグネチャで使用できる変数であり、同じ未指定の型を複数回参照できます。一方、 a は、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ではこれらの概念について説明しているさらに詳しく説明し、追加のリソースを参照します。

新しいタイプ

ANewTypeは、実際に新しい型を作成する作業を実行せずに、または新しいクラス インスタンスを作成するオーバーヘッドを心配せずに、異なる型を宣言する場合に使用します。

型チェッカーでは、 「Name」という名前NewType('Name', int)のサブクラスを作成しますint

実行時には、NewType('Name', int)はまったくクラスではなく、実際には恒等関数であるため、x is NewType('Name', int)(x)常に true になります。

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

おすすめ記事