我已经定义了一个抽象基类BaseRepository
,它充当具有指定超类型Foo
的项的集合。
BaseRepository
中的便捷类方法带有注释/类型提示,可用于Foo
类型的对象。这是一个最小的例子:
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
现在有多个静态实现(例如SubRepository
),每个实现都应该使用它们自己的项类型(如Bar
),它们是原始泛型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()
存储库是静态的,这意味着它们不是实例化的,而是充当命名空间,以便正确访问我从YAML配置文件加载的项目。主要的好处是我可以创建其中一个SubRepositories
并简单地覆盖反序列化方法_load_items
,结果存储库将具有基类中的所有便捷方法。由于我需要确保所有这些SubRepositories
使用具有特定接口的项Foo
以使BaseRepository
方法正常运行,因此SubRepositories
必须使用项目继承自Foo
。
Java或C#等强类型语言具有通用集合的概念,其中子类集合中的元素都采用特定类型。
Python中的类型提示是否可以相同?
特别是,我希望get_item
中的继承SubRepository
方法以最小的努力被暗示为Bar
(不仅仅为了类型提示而覆盖它)。最理想的是,PyCharm应该使用正确的返回值。
目前,即使SubRepository
包含Bar
个项目,我在PyCharm中的自动完成功能也只会显示Foo
的成员。
我了解了typing.Generic
和TypeVar
,但我不确定如何在这种情况下使用它们。
答案 0 :(得分:2)
您正在编程接口,因此只会公开expressionChangedAfterItHasBeenCheckedError
个成员。
Foo
输出:
from typing import get_type_hints
print(get_type_hints(SubRepository.get_item))
通用集合将公开泛型类型的成员。
{'return': <class '__main__.Foo'>}
返回类型
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()
通过降压
print(get_type_hints(SubRepository.get_item))
自动填充功能现在会显示{'return': ~T}
的成员。