Python 类型:返回类型与 Java Clazz<T> 中的 Clazz[T] 等泛型
Posted
技术标签:
【中文标题】Python 类型:返回类型与 Java Clazz<T> 中的 Clazz[T] 等泛型【英文标题】:Python typing: return type with generics like Clazz[T] as in Java Clazz<T> 【发布时间】:2020-01-11 23:52:20 【问题描述】:所以我知道 Python 的 typing.Optional
。但我自己写了粗略的PyOptional
(代码here),并想将Optional[T]
与我的PyOptional
结合到PyOptional[T]
。
我目前正在使用 Python 3.7 并尝试扩展 typing.Optional
。
我的一些PyOptional
:
class PyOptional:
T: TypeVar = TypeVar("T")
def __init__(self, obj: T):
self.value: Any = obj
def get(self) -> Optional[T]:
return self.value
def or_else(self, default) -> T:
return self.value or default
我想要的伪代码:
def find_user_by_id(id: int) -> PyOptional[User]:
return PyOptional(db.find_user_by_id(id))
目标是让我的 IDE 能够检查预期的返回类型,并且仍然能够在返回的对象上调用我的方法。所以它必须符合 PEP。
【问题讨论】:
【参考方案1】:您应该查看有关泛型的文档——具体来说,user-defined generics。 mypy 文档也有一个完整的overview of generics,可供参考。
在这种特殊情况下,您希望通过添加Generic[T]
作为类基来使整个类通用。仅在单个函数签名中使用 T
将使每个 individual 函数通用,而不是整个类:
from typing import TypeVar, Generic, Optional
T = TypeVar("T")
class PyOptional(Generic[T]):
def __init__(self, obj: Optional[T]) -> None:
self.value = obj
def get(self) -> Optional[T]:
return self.value
def or_else(self, default: T) -> T:
return self.value or default
一些补充说明:
不要为任何 TypeVar 变量添加注释。在这里,T
是一种元类型构造,用作“洞”/可以表示任意数量的类型。所以,给它分配一个固定的类型并没有什么意义,而且会混淆类型检查器。
永远不要在任何给定的签名中只使用一次 TypeVar - 使用 TypeVars 的全部意义在于您可以声明两个或多个类型总是相同的。
请注意,上面固定的 PyOptional 类也遵守此规则。例如,以get
为例。现在我们使整个类成为通用的,这个函数的类型签名现在基本上类似于def get(self: PyOptional[T]) -> Optional[T]
。之前,更像是def get(self: PyOptional) -> Optional[T]
。
为了使您的类有意义,您可能希望您的构造函数接受Optional[T]
而不仅仅是T
。
制作self.value
Any 可能是不必要的/不必要地太模糊了。我们可以省略类型提示,现在它的推断类型将是Optional[T]
。
如果您想更彻底地检查您的课程是否符合 PEP 484 并且可能会被 PyCharm 等 IDE 理解,请考虑通过 mypy(PEP 484)使用您的课程对您的课程 + 一些代码进行类型检查类型检查器。
这并不能保证您的 IDE 将完全理解您的类(因为它可能无法完全实现有关 PEP 484 的所有内容/您可能会在 mypy 或您的 IDE 中遇到错误),但它应该可以帮助您非常接近.
【讨论】:
谢谢!这正是我想要的,我可以确认它有效!以上是关于Python 类型:返回类型与 Java Clazz<T> 中的 Clazz[T] 等泛型的主要内容,如果未能解决你的问题,请参考以下文章
Python 数据类型中的“冒号“[::]----分片与步长