在泛型集合中指定重写方法的类型提示 [英] Specifying type hints of overridden methods in generic collection
问题描述
我定义了一个抽象基类 BaseRepository
,它充当具有指定超类型 Foo
的项目集合。
BaseRepository
中的便利性classmethods被注释/类型暗示用于处理类型为 Foo
的对象。这里是一个简单的例子: $ ab
$ b
from abc import ABCMeta,abstractmethod
NoReturn = None
class Foo(object):
pass#简单数据保存对象
$ b $ class BaseRepository(object,metaclass = ABCMeta):
#可能是后面填充'Foo`的子类型
_items = None#type:List [Foo]
@classmethod
def get_item(cls) - > Foo:
return cls._items [0]
@classmethod
@abstractmethod
def _load_items(cls) - > NoReturn:
pass
现在有多个静态实现(例如 SubRepository
),它们都应该与它们自己的类型的项目一起工作(例如 Bar
),它是原始泛型类型<$ c $的子类c> Foo 。
class Bar(Foo):
pass#必须实现Foo为了使BaseRepository的方法能够工作
$ b $ def load_some_bars():
return [Bar(),Bar()]
class SubRepository(BaseRepository):
#从BaseRepository继承`get_item`
@classmethod
def _load_items(cls) - > NoReturn:
cls._items = load_some_bars()
存储库是静态的,这意味着它们没有实例化,而是作为命名空间来正确访问从YAML配置文件加载的项目。主要的优点是我可以创建这些 强类型语言(如Java或C#)具有泛型集合的概念,其中子类集合中的元素都假设一个特定的类型。 SubRepositories
中的一个,并简单地覆盖反序列化方法 _load_items
,并且生成的存储库将有基类的所有便利方法。因为我需要确保所有这些 SubRepositories
处理具有特定接口的项目 Foo
,以使 BaseRepository
方法正常工作, SubRepositories
必须适用于从 Foo $ c
项目,我在PyCharm中的自动完成只显示
在Python中使用类型提示可能是相同的吗?
特别是,我希望将 SubRepository
中继承的 get_item
方法暗示为 Bar
用最小的努力(不会仅仅为了提示类型而重写它)。目前,尽管 SubRepository
拥有<$ c $, c> Bar Foo
的成员。
我读了 typing.Generic
和 TypeVar
,但我不确定如何在这种情况下使用它们。
您正在编程接口,所以只有 foo
成员被暴露。
from type import get_type_hints
print get_type_hints(SubRepository.get_item))
输出:
{'return':< class'__main __。Foo'>}
泛型集合将公开泛型类型的成员。
从键入import TypeVar,Generic,get_type_hints
from abc import ABCMeta,abstractmethod
NoReturn = None
#带有上限的类型变量
T = TypeVar('T',bound = Foo)
class BaseRepository(Generic [T],metaclass = ABCMeta):
_items = None #type:List [T]
@classmethod
def get_item(cls ) - > T:
return cls._items [0]
@classmethod
@abstractmethod
def _load_items(cls) - > NoReturn:
pass
class SubRepository(BaseRepository [Bar]):
#从BaseRepository继承`get_item`
@classmethod
def _load_items(cls) - > NoReturn:
cls._items = load_some_bars()
返回类型
print(get_type_hints(SubRepository.get_item))
通过降价
{'return':〜T}
Autocompletion现在会显示 Bar的成员
。
I have defined an abstract base class BaseRepository
that acts as a collection of items with specified supertype Foo
.
The convenience classmethods in BaseRepository
are annotated/type hinted to work with objects of type Foo
. Here is a minimal example:
from abc import ABCMeta, abstractmethod
NoReturn = None
class Foo(object):
pass # simple data holding object
class BaseRepository(object, metaclass=ABCMeta):
# May be filled with subtypes of `Foo` later
_items = None # type: List[Foo]
@classmethod
def get_item(cls) -> Foo:
return cls._items[0]
@classmethod
@abstractmethod
def _load_items(cls) -> NoReturn:
pass
Now there are multiple static implementations (e.g. SubRepository
) which are each supposed to work with their own type of items (like Bar
), being subclasses of the original generic type Foo
.
class Bar(Foo):
pass # Must implement Foo in order for BaseRepository's methods to work
def load_some_bars():
return [Bar(),Bar()]
class SubRepository(BaseRepository):
# Inherits `get_item` from BaseRepository
@classmethod
def _load_items(cls) -> NoReturn:
cls._items = load_some_bars()
The repositories are static, meaning that they are not instantiated but rather function as namespaces for proper access to items that I load from YAML configuration files. The main perk is that I can create one of these SubRepositories
and simply override the deserialization method _load_items
, and the resulting repository will have all convenience methods from the base class. As I need to ensure that all of these SubRepositories
work with items Foo
that have a specific interface in order for the BaseRepository
methods function properly, the SubRepositories
must work with items that inherit from Foo
.
Strongly-typed languages like Java or C# have the concept of Generic Collections, where the elements in the subclassed collections all assume a specific type.
Is the same possible with type hinting in Python?
In particular, I would like the inherited get_item
method in SubRepository
to be hinted as Bar
with minimal effort (not override it just for the sake of type hints). Optimally, the correct return value should be linted by PyCharm.
Currently, even though SubRepository
holds Bar
items, my autocompletion in PyCharm only shows me members of Foo
.
I read about typing.Generic
and TypeVar
, but I'm unsure how to use them in this case.
You're programming to an interface, so only Foo
members are exposed.
from typing import get_type_hints
print(get_type_hints(SubRepository.get_item))
Output:
{'return': <class '__main__.Foo'>}
A generic collection will expose the generic type's members.
from typing import TypeVar, Generic, get_type_hints
from abc import ABCMeta, abstractmethod
NoReturn = None
# type variable with an upper bound
T = TypeVar('T', bound=Foo)
class BaseRepository(Generic[T], metaclass=ABCMeta):
_items = None # type: List[T]
@classmethod
def get_item(cls) -> T:
return cls._items[0]
@classmethod
@abstractmethod
def _load_items(cls) -> NoReturn:
pass
class SubRepository(BaseRepository[Bar]):
# Inherits `get_item` from BaseRepository
@classmethod
def _load_items(cls) -> NoReturn:
cls._items = load_some_bars()
Return type
print(get_type_hints(SubRepository.get_item))
Passes the buck
{'return': ~T}
Autocompletion will now show members of Bar
.
这篇关于在泛型集合中指定重写方法的类型提示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!