from dataclasses import dataclass
@dataclass
class BaseProduct:
...
@dataclass
class ProductA(BaseProduct):
a_specific_id: int
@dataclass
class ProductSubmissionCommand:
product_id: str
product: BaseProduct
class AProductRequestSubmitter:
def __call__(self, job_id: int, cmd: ProductSubmissionCommand):
...
cmd.product.a_specific_id
mypy 錯誤是:
error: "BaseProduct" has no attribute "a_specific_id"
如何AProductRequestSubmitter.__call__正確注釋?此類特定于AProduct,對于不同的產品型別還有其他提交者。
是否可以以某種方式使用通用型別或文字值?或者也許 cast 或 assert 是唯一的方法?
uj5u.com熱心網友回復:
你有兩種可能的方法。
getattr通過使用顯式呼叫忽略靜態型別class AProductRequestSubmitter: def __call__(self, job_id: int, cmd: ProductSubmissionCommand): ... getattr(cmd.product, 'a_specific_id')用于專注
Generic于靜態型別的觀點:ProductSubmissionCommandT = TypeVar("T", bound=BaseProduct) @dataclass class ProductSubmissionCommand(Generic[T]): product_id: str product: T class AProductRequestSubmitter: def __call__(self, job_id: int, cmd: ProductSubmissionCommand[ProductA]): pass
uj5u.com熱心網友回復:
有多種方法可以實作您的目標,我將展示那些現在突然出現在我腦海中的方法。
在運行時確保正確的型別
可能有多個孩子BaseProduct作為他們的父母,并且型別檢查器無法確定,您永遠不會傳遞ProductSubmissionCommand具有型別的屬性的實體,product該型別的子型別BaseProduct沒有a_specific_id屬性。為了確保這永遠不會發生,您可以使用型別斷言開始您的函式呼叫,例如:
class AProductRequestSubmitter:
def __call__(self, job_id: int, cmd: ProductSubmissionCommand):
if not isinstance(cmd.product, ProductA):
raise TypeError(f"Only 'ProductA' instances are allowed, not '{cmd.product.__class__.__name__}'")
...
cmd.product.a_specific_id
Pycharm(或任何其他靜態型別檢查器)現在應該是安靜的,因為程式永遠不會到達代碼的一部分,a_specific_id除非使用了正確的型別,否則可以訪問該部分。
子類ProductSubmissionCommand
如果您真的打算使用AProductRequestSubmitterfor 實體,其中ProductSubmissionCommand有producttype ProductA,您可以將您的子類ProductSubmissionCommand和 typehint 其product屬性作為ProductA實體。
@dataclass
class ProductASubmissionCommand(ProductSubmissionCommand):
product: ProductA
class AProductRequestSubmitter:
def __call__(self, job_id: int, cmd: ProductASubmissionCommand):
...
cmd.product.a_specific_id
同樣,所有聰明的型別檢查器現在都應該明白,那cmd總是有product.a_specific_id屬性的。
采用Protocol
使用:
class ProductASubmissionCommand(Protocol):
product: ProductA
class AProductRequestSubmitter:
def __call__(self, job_id: int, cmd: ProductASubmissionCommand):
...
cmd.product.a_specific_id
You are basically saying "accept anything, that has an attribute named product of a type ProductA". This is a little hacky and makes you create a protocol subclass only for the sake of typehinting this single method call, but, again, should work with all static type checkers.
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/426692.html
下一篇:如何將泛型型別與1進行比較
