假设我有一个通用的Store
类,它实现了各种方法来检索StoreObjects
。为了填充存储,它定义了一个抽象方法load_object
。你知道吗
然后我创建一个CarStore
。我从Store
派生并覆盖load_object
方法以返回Car
对象。你知道吗
现在的问题是如何为此添加类型提示。首先是代码:
from typing import Dict
import weakref
import abc
class StoreObject:
pass
class Car(StoreObject):
def __init__(self, color: str):
self.color = color # type: str
class Store(abc.ABC):
def __init__(self):
self._cache = weakref.WeakValueDictionary() # type: weakref.WeakValueDictionary[int, StoreObject]
def get(self, index: int) -> StoreObject:
try:
return self._cache[index]
except KeyError:
obj = self.load_object(index)
self._cache[index] = obj
return obj
@abc.abstractmethod
def load_object(self, index: int) -> StoreObject:
raise NotImplementedError
class CarStore(Store):
def load_object(self, index: int) -> Car:
if index < 100:
return Car("red")
else:
return Car("blue")
store = CarStore()
car = store.get(10)
print("Your car color is", car.color)
问题出现在以下行中:
print("Your car color is", car.color)
这里PyCharm
给出了以下警告:
Unresolved attribute reference 'color' for class 'StoreObject'
Mypy
给出以下错误:
development/storetyping.py:39: error: "StoreObject" has no attribute "color"
而且PyCharm
代码完成显然不包括name
的store.get(10).?
方法。你知道吗
如何键入基类以便PyCharm
和mypy
可以成功地检查此代码?你知道吗
有没有办法参数化Store
中的类型,以便在创建CarStore
时,我可以告诉它在注释中使用Car
而不是StoreObject
?你知道吗
您的类型检查工作正常;
get
在CarStore
中没有被重写,因此它的注释继续指定它返回StoreObject
。如果要更改注释,必须在CarStore
中重新定义get
,例如添加:确保
import typing
可以访问cast
(或者使用不合格的cast
并将其添加到from typing import Dict
导入中)。你知道吗为了避免运行时性能开销,您只能基于
if typing.TYPE_CHECKING:
测试有条件地定义get
(当静态检查器分析代码时返回True
,运行代码时返回False
),因此get
重载实际上在运行时没有定义。你知道吗在更静态的语言中,您可以创建
Store
作为泛型类,并在从Store
继承时使用Car
作为类型参数。你知道吗实际上,我们可以使用python中的
typing
模块来实现这一点。你知道吗下面是一个简单的例子:
编辑:
为了解决ShadowRanger的问题:如果您希望Car和所有产品都有一个公共基类,那么可以使用
bound
的TypeVar
参数。谢谢您胡安帕.阿里维拉加为了提示。你知道吗所以我们创建一个产品类并将
TypeVar
绑定到它。你知道吗Mypy现在会抱怨:
因为
Car
不是Product
。所以让我们也改变一下:现在,玛比很高兴。你知道吗
编辑2:
下面是带有更多注释的完整代码,这些注释甚至使
mypy strict
感到高兴。你知道吗相关问题 更多 >
编程相关推荐