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类型错误是:error: "BaseProduct" has no attribute "a_specific_id"
如何正确注释AProductRequestSubmitter.__call__?这个类是特定于AProduct的,还有针对不同产品类型的其他提交者。
是否可以以某种方式使用泛型类型或文字值?或者说演员或断言是唯一的出路?
发布于 2022-01-31 13:14:40
你有两种可能的方法。
getattr调用忽略静态类型。类AProductRequestSubmitter: def __call__(self,job_id: int,cmd: ProductSubmissionCommand):getattr( 'a_specific_id'),cmd.product
Generic从静态类型的角度专门化ProductSubmissionCommand:T= TypeVar("T",bound=BaseProduct) @dataclass class ProductSubmissionCommand(GenericT):product_id: str产品:t class AProductRequestSubmitter: def __call__(self,job_id: int,cmd: ProductSubmissionCommandProductA):pass
发布于 2022-01-31 12:34:27
有很多种方法可以达到你想要达到的目的,我会展示那些在我头上突然冒出来的方法。
在运行时确保正确的类型
可能有多个以BaseProduct作为父级的子实例,并且类型检查器无法确定地知道,您将永远不会传递一个ProductSubmissionCommand实例,该实例具有一个类型的product属性,该类型是没有a_specific_id属性的BaseProduct的子实例。为了确保这种情况永远不会发生,您可以使用类型断言启动函数调用,如:
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_idPycharm (或任何其他静态类型检查器)现在应该是安静的,因为程序永远不会到达代码的一部分,除非使用正确的类型,否则将访问a_specific_id。
子类ProductSubmissionCommand
如果您真的计划对实例使用AProductRequestSubmitter,其中ProductSubmissionCommand的product类型为ProductA,则可以对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您基本上是在说“接受任何东西,它有一个名为product的ProductA类型的属性”。这有点麻烦,让您创建一个协议子类只是为了输入这个方法调用,但是,同样,它应该与所有静态类型检查器一起工作。
https://stackoverflow.com/questions/70923977
复制相似问题