我正在嘗試在 Python 中撰寫一個類層次結構,以便子類可以覆寫一個方法predict以具有更窄的回傳型別,該型別本身就是父回傳型別的子類。當我實體化子類的實體并呼叫時,這似乎作業正常predict;回傳值具有預期的窄型別。predict_batch但是,當我呼叫在自身呼叫的基類 () 上定義的不同函式時predict,窄回傳型別會丟失。
一些背景:我的程式必須支持使用兩種型別的影像分割模型,“實體”和“語意”。這兩個模型的輸出非常不同,所以我想用對稱的類層次結構來存盤它們的輸出(即BaseResult、InstResult和SemResult)。BaseResults當不需要知道使用了哪種特定型別的模型時,這將允許一些客戶端代碼通用。
這是一個玩具代碼示例:
from abc import ABC, abstractmethod
from typing import List
from overrides import overrides
##################
# Result classes #
##################
class BaseResult(ABC):
"""Abstract container class for result of image segmentation"""
pass
class InstResult(BaseResult):
"""Stores the result of instance segmentation"""
pass
class SemResult(BaseResult):
"""Stores the result of semantic segmentation"""
pass
#################
# Model classes #
#################
class BaseModel(ABC):
def predict_batch(self, images: List) -> List[BaseResult]:
return [self.predict(img) for img in images]
@abstractmethod
def predict(self, image) -> BaseResult:
raise NotImplementedError()
class InstanceSegModel(BaseModel):
"""performs instance segmentation on images"""
@overrides
def predict(self, image) -> InstResult:
return InstResult()
class SemanticSegModel(BaseModel):
"""performs semantic segmentation on images"""
@overrides
def predict(self, image) -> SemResult:
return SemResult()
########
# main #
########
# placeholder for illustration
images = [None, None, None]
model = InstanceSegModel()
single_result = model.predict(images[0]) # has type InstResult
batch_result = model.predict_batch(images) # has type List[BaseResult]
在上面的代碼中,我希望batch_result有 type List[InstResult]。
At runtime, none of this matters, and my code executes just fine. But the static type checker (Pylance) in my editor (VS Code) doesn't like how the client code assumes batch_result is the more narrow type. I can only think of these two possible solutions, but neither feels clean to me:
- Use the
castfunction from thetypingmodule - Override
predict_batchin the subclasses even though the logic doesn't change
uj5u.com熱心網友回復:
您可以一起使用泛型和繼承來覆寫/縮小父類中的注釋
from typing import List, Generic, TypeVar
T = TypeVar('T')
class BaseModel(ABC, Generic[T]):
def predict_batch(self, images: List) -> List[T]:
return [self.predict(img) for img in images]
@abstractmethod
def predict(self, image) -> T:
raise NotImplementedError()
class InstanceSegModel(BaseModel[InstResult]):
"""performs instance segmentation on images"""
@overrides
def predict(self, image) -> InstResult:
return InstResult()
class SemanticSegModel(BaseModel[SemResult]):
"""performs semantic segmentation on images"""
@overrides
def predict(self, image) -> SemResult:
return SemResult()
images = [None, None, None]
model = InstanceSegModel()
single_result = model.predict(images[0]) # has type InstResult
batch_result = model.predict_batch(images) # has type List[InstResult]
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/443834.html
標籤:python inheritance typing pylance
上一篇:創建繼承類并列印父類陣列中的資料
下一篇:需要想法如何決議以下JSON格式
