首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在签名中注释特定的dataclass子类

在签名中注释特定的dataclass子类
EN

Stack Overflow用户
提问于 2022-01-31 09:51:14
回答 2查看 82关注 0票数 0
代码语言:javascript
复制
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的,还有针对不同产品类型的其他提交者。

是否可以以某种方式使用泛型类型或文字值?或者说演员或断言是唯一的出路?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-31 13:14:40

你有两种可能的方法。

  1. 通过使用显式getattr调用忽略静态类型。

类AProductRequestSubmitter: def __call__(self,job_id: int,cmd: ProductSubmissionCommand):getattr( 'a_specific_id'),cmd.product

  1. 使用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

票数 1
EN

Stack Overflow用户

发布于 2022-01-31 12:34:27

有很多种方法可以达到你想要达到的目的,我会展示那些在我头上突然冒出来的方法。

在运行时确保正确的类型

可能有多个以BaseProduct作为父级的子实例,并且类型检查器无法确定地知道,您将永远不会传递一个ProductSubmissionCommand实例,该实例具有一个类型的product属性,该类型是没有a_specific_id属性的BaseProduct的子实例。为了确保这种情况永远不会发生,您可以使用类型断言启动函数调用,如:

代码语言:javascript
复制
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

如果您真的计划对实例使用AProductRequestSubmitter,其中ProductSubmissionCommandproduct类型为ProductA,则可以对ProductSubmissionCommand进行子类,并将其product属性键入为ProductA实例。

代码语言:javascript
复制
@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

使用:

代码语言:javascript
复制
class ProductASubmissionCommand(Protocol):
    product: ProductA

class AProductRequestSubmitter:
    def __call__(self, job_id: int, cmd: ProductASubmissionCommand):
        ...
        cmd.product.a_specific_id

您基本上是在说“接受任何东西,它有一个名为productProductA类型的属性”。这有点麻烦,让您创建一个协议子类只是为了输入这个方法调用,但是,同样,它应该与所有静态类型检查器一起工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70923977

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档