问题描述
所以我知道python的类型.可选.但是我写了我自己的原始PyOptional( https://github.com/felixhertrampf/PyOptional/blob/master/PyOptional.py ),并希望将Optional [T]与我的PyOptional合并为PyOptional [T].
So I am aware of pythons typing.Optional. But I wrote my own crude PyOptional (https://github.com/felixhertrampf/PyOptional/blob/master/PyOptional.py) and would like to combine Optional[T] with my PyOptional to PyOptional[T].
我目前正在使用Python 3.7,并尝试扩展键入.
I am currently using Python 3.7 and tried extending typing.Optional.
我的一些PyOptional
Some of my 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.
The goal is for my IDE to be able to check what return type to expect and still be able to invoke my methods on the returned object. So it would have to be PEP compliant.
推荐答案
您应该阅读有关泛型的文档-具体来说,用户定义的类属.mypy文档还具有全面的泛型概述,可用于参考
You should review the documentation on generics -- specifically, user-defined generics. The mypy docs also have a thorough overview of generics that can be useful to reference.
在这种特殊情况下,您想通过添加 Generic [T]
作为类库来使整个类具有通用性.仅在各个函数签名中使用 T
即可使每个单个函数通用,而不是整个类:
In this particular case, you want to make the entire class generic by adding in a Generic[T]
as a class base. Just using T
in the individual function signatures will make each individual function generic, but not the class as a whole:
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
是一种元类型构造,用作空洞"/可以表示任意数量的类型.因此,将其分配为固定类型实际上没有任何意义,并且会混淆类型检查器.
Don't add an annotation for any TypeVar variable. Here,
T
is a sort of meta-type construct that serves as "hole"/can represent any number of types. So, assigning it a fixed type doesn't really make sense, and will confuse type checkers.
在任何给定的签名中都不要仅使用TypeVar一次-使用TypeVars的要点是,这样您就可以声明两个或多个类型总是相同的.
Never use a TypeVar only once in any given signature -- the whole point of using TypeVars is so that you can declare two or more types are always going to be the same.
请注意,上面的固定PyOptional类也遵守此规则.例如,使用 get
.现在我们使整个类通用,此函数的类型签名现在基本上类似于 def get(self:PyOptional [T])->可选[T]
.以前,它更像是 def get(self:PyOptional)->可选[T]
.
Note that the fixed PyOptional class above also obeys this rule. For example, take get
. Now that we made the whole class generic, the type signature for this function is now basically something like def get(self: PyOptional[T]) -> Optional[T]
. Before, it was more like def get(self: PyOptional) -> Optional[T]
.
为了使您的类更有意义,您可能希望构造函数接受 Optional [T]
,而不只是 T
.
For your class to make sense, you probably want your constructor to accept an Optional[T]
instead of just T
.
设置 self.value
可能是不必要的,也不一定是太含糊.我们可以省略类型提示,现在它将具有 Optional [T]
的推断类型.
Making self.value
Any is probably unnecessary/is unnecessarily too vague. We can leave off the type hint, and now it'll have an inferred type of Optional[T]
.
如果您想更彻底地检查您的班级是否符合PEP 484,并可能被诸如PyCharm之类的IDE理解,请考虑通过.
If you want to more thoroughly check whether or not your class is PEP 484 compliant and will likely be understood by IDEs such as PyCharm, consider type-checking your class + some code using your class via mypy, a PEP 484 type checker.
这不能保证您的IDE会完全理解您的类(因为它可能无法完全实现有关PEP 484的所有内容/您可能会在mypy或IDE中遇到错误),但是它应该可以帮助您更加接近.
This won't guarantee that your IDE will fully understand your class (since it might not fully implement everything about PEP 484/you might run into a bug in either mypy or your IDE), but it should help you get pretty close.
这篇关于Python类型:Java Clazz& lt; T& gt;中带有Clazz [T]之类的泛型的返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!