TypeVar 和 NewType 有什么区别? [英] What is the difference between TypeVar and NewType?

查看:53
本文介绍了TypeVar 和 NewType 有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TypeVarNewType 似乎相关,但我不确定当我应该使用每个或在运行时和静态时有什么区别.

TypeVar and NewType seem related but I'm not sure when I'm supposed to use each or what the difference is at runtime and statically.

推荐答案

这两个概念的相关性并不比任何其他类型相关的概念多.

The two concepts aren't related any more than any other type-related concepts.

简而言之,TypeVar 是一个可以在类型签名中使用的变量,因此您可以多次引用相同的未指定类型,而 NewType 用于告诉类型检查器某些值应该被视为它们自己的类型.

In short, a TypeVar is a variable you can use in type signatures so you can refer to the same unspecified type more than once, while a NewType is used to tell the type checker that some values should be treated as their own type.

为简化起见,类型变量让您可以多次引用同一个类型,而无需具体指定它是哪种类型.

To 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.

# (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_oneValueHolder.get 的类型.

Without type variables, there wouldn't be a good way to declare the type of get_one or ValueHolder.get.

TypeVar 上还有一些其他选项.您可以通过传入更多类型来限制可能的值(例如 TypeVar(name, int, str)),或者您可以给出一个上限,因此类型变量的每个必须值都必须是该类型(例如 TypeVar(name, bound=int)).

There are a few other options on TypeVar. You can restrict the possible values by passing in more types (e.g. TypeVar(name, int, str)), or you can give an upper bound so every must value of the type variable must be a subtype of that type (e.g. TypeVar(name, bound=int)).

此外,您可以在声明类型变量时决定它是协变的、逆变的还是两者都不是.这实质上决定了何时可以使用子类或超类来代替泛型类型.PEP 484 更详细地描述了这些概念,并且指的是额外的资源.

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.

NewType 用于当您想声明一个不同的类型而不实际执行创建新类型的工作或担​​心创建新类实例的开销时.

A NewType 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.

在类型检查器中,NewType('Name', int) 创建一个名为Name"的 int 子类.

In the type checker, NewType('Name', int) creates a subclass of int named "Name."

在运行时,NewType('Name', int) 根本不是一个类;它实际上是恒等函数,所以 x is NewType('Name', int)(x) 总是为真.

At runtime, NewType('Name', int) is not a class at all; it is actually the identity function, so x is NewType('Name', int)(x) is always 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 看起来像这样:

To the type checker, UserId looks something like this:

class UserId(int): pass

但在运行时,UserId 基本上就是这样:

But at runtime, UserId is basically just this:

def UserId(x): return x

在运行时对于 NewType 几乎没有什么比这更重要的了.从 Python 3.8 开始,它的实现几乎完全一样如下:

There's almost nothing more than that to a NewType at runtime. As of Python 3.8, its implementation is almost exactly as follows:

def NewType(name, type_):
    def identity(x):
        return x
    identity.__name__ = name
    return identity

这篇关于TypeVar 和 NewType 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆