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]) -&gt; Optional[T]。之前,更像是def get(self: PyOptional) -&gt; 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 数据类型中的“冒号“[::]----分片与步长

Java方法与数组

在 Java 中使用 if 与三元运算符时的“错误”返回类型

java基本类型与封装类型

java-协变返回类型

java-协变返回类型