[英]Annotating specific dataclass subclass in a signature
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__
? 此 class 专用于AProduct
,还有针对不同产品类型的其他提交者。
是否可以以某种方式使用通用类型或文字值? 或者,强制转换或断言是 go 的唯一方法?
有多种方法可以实现您的目标,我将展示那些现在突然出现在我脑海中的方法。
可能有多个子级以BaseProduct
作为其父级,并且类型检查器无法确定,您永远不会传递ProductSubmissionCommand
实例,该实例具有的product
属性类型是BaseProduct
的子级,但没有a_specific_id
属性. 为了确保这永远不会发生,您可以使用类型断言开始您的 function 调用,例如:
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(或任何其他 static 类型检查器)现在应该是安静的,因为程序永远不会到达代码的一部分,除非使用了正确的类型,否则访问a_specific_id
的部分。
ProductSubmissionCommand
如果您确实打算将AProductRequestSubmitter
用于实例,其中ProductSubmissionCommand
具有ProductA
类型的product
,您可以将您的ProductSubmissionCommand
子类化并将其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
您基本上是在说“接受任何具有名为ProductA
类型的product
的属性”。 这有点 hacky,让您创建一个协议子类只是为了对这个单一的方法调用进行类型提示,但同样,它应该适用于所有 static 类型检查器。
你有两种可能的方法。
通过使用显式getattr
调用忽略 static 类型
class AProductRequestSubmitter: def __call__(self, job_id: int, cmd: ProductSubmissionCommand): ... getattr(cmd.product, 'a_specific_id')
使用Generic
在 static 打字观点上专门化ProductSubmissionCommand
:
T = 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.