【问题标题】:Call constructor of type parameter in generic class在泛型类中调用类型参数的构造函数
【发布时间】:2021-08-17 19:43:07
【问题描述】:

我正在通过AnyStr 编写一个通用类,因此允许bytesstr

class MyObject(Generic[AnyStr]):
   ...

在这个类的(多个)方法内部,我想构造空字节或空字符串对象,b'''',具体取决于类型参数。我该怎么做?

【问题讨论】:

  • 如果来电者提前知道他们想要MyObject[str] 还是MyObject[bytes],而不是自己拥有AnyStr 并转发到MyObject,我会想到一个答案。这个条件成立吗?
  • @MarioIshac 确实如此!

标签: python-3.x type-hinting mypy python-typing


【解决方案1】:

您应该有一个基类,其中的共享方法适用于 strbytes 以利用共同行为(例如,strbytes 都具有长度,或者 strbytes 是可索引的),以及为特定行为提供实现的两个子类。要强制子类提供这些特定行为(这样mypy 可以假定对其特定方法的调用将在基类中成功),您可以在基类中创建等效的@abstractmethod

这就是它的样子:

from abc import abstractmethod, ABC
from typing import AnyStr, Generic, final

class MyObject(ABC, Generic[AnyStr]):
    @classmethod
    @abstractmethod
    def empty(cls) -> AnyStr:
        pass

    def __init__(self, data: AnyStr):
        self.data: AnyStr = data

    # Example shared method.
    def is_empty(self) -> bool:
        # Assume that for the sake of the example we can't do `len(self.data) == 0`, and that we need
        # to check against `empty()` instead.
        return self.data == self.__class__.empty()

class MyStr(MyObject[str]):
    @classmethod
    @final
    def empty(cls) -> str:
        return ""

class MyBytes(MyObject[bytes]):
    @classmethod
    @final
    def empty(cls) -> bytes:
        return b""

我们将empty() 设为类方法而不是实例方法,因为它不依赖具有特定数据的实例来了解空的str / bytes 的样子。

此外,我们将 empty() 设为 final 方法,因此想要进一步提供特定行为的 MyStr 或 MyBytes` 的子类不会改变被认为是“空”的内容(因为只有一件事可以认为是空的)。

以上所有内容都将在mypy --strict下进行类型检查。

在调用方,他们永远不会实例化 MyObject[str]MyObject[bytes](事实上,mypy 会阻止这种情况,正如我们所希望的,因为 MyObject 没有 empty() 的实现) .相反,因为你在 cmets 中说调用者会提前知道他们想要bytes 还是str,所以他们直接实例化MyStrMyBytes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-05
    • 1970-01-01
    相关资源
    最近更新 更多