Hızlı yanıt: kod örneği
The two concepts aren't related any more than any other type-related concepts.In short, a is a variable you can use in type signatures so you can refer to the same unspecified type more than once, while a is used to tell the type checker that some values should be treated as their own type.Type VariablesTo simplify, type variables let you refer to the same type more than once without specifying exactly which type it is.In a definition, a single type variable always takes the same value.Without type variables, there wouldn't be a good way to declare the type of or .There are a few other options on . You can restrict the possible values by passing in more types (e.g. ), or you can give an upper bound so every value of the type variable must be a subtype of that type (e.g. ).Additionally, you can decide whether a type variable is covariant, contravariant, or neither when you declare it. This essentially decides when subclasses or superclasses can be used in place of a generic type. PEP 484 describes these concepts in more detail, and refers to additional resources.NewTypeA is for when you want to declare a distinct type without actually doing the work of creating a new type or worry about the overhead of creating new class instances.In the type checker, creates a subclass of named "Name."At runtime, is not a class at all; it is actually the identity function, so is always true.To the type checker, looks something like this:But at runtime, is basically just this:There's almost nothing more than that to a at runtime. As of Python 3.8.1, its implementation is almost exactly as follows:
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 RT = TypeVar('T')R = TypeVar('R')# Put in a list of Ts and get out one Tdef get_one(x: List[T]) -> T: ...# Put in a T and an R, get back an R and a Tdef swap(x: T, y: R) -> Tuple[R, T]: return y, x# A simple generic class that holds a value of type Tclass ValueHolder(Generic[T]): def __init__(self, value: T): self.value = value def get(self) -> T: return self.valuex: ValueHolder[int] = ValueHolder(123)y: ValueHolder[str] = ValueHolder('abc')
get_one
ValueHolder.get
TypeVar
TypeVar(name, int, str)
TypeVar(name, bound=int)
NewType
NewType('Name', int)
int
NewType('Name', int)
x is NewType('Name', int)(x)
from typing import NewTypeUserId = NewType('UserId', int)def get_user(x: UserId): ...get_user(UserId(123456)) # this is fineget_user(123456) # that's an int, not a UserIdUserId(123456) + 123456 # fine, because UserId is a subclass of int
UserId
class UserId(int): pass
UserId
def UserId(x): return x
NewType
def NewType(name, type_): def identity(x): return x identity.__name__ = name return identity