在泛型中调用类型参数的构造函数 class
Call constructor of type parameter in generic class
我正在 AnyStr
上写一个通用的 class,所以允许 bytes
或 str
。
class MyObject(Generic[AnyStr]):
...
在此 class 的(多个)方法中,我想根据类型参数构造空字节或空字符串对象 b''
或 ''
。我该怎么做?
您应该有一个基础 class,其共享方法适用于 str
和 bytes
,它们利用共同的行为(例如,str
和bytes
具有长度,或者 str
和 bytes
都可索引),以及两个子 class 提供特定行为的实现。为了强制 subclasses 提供那些特定的行为(这样 mypy
可以假设调用它们的特定方法会在基础 class 中成功),你做一个等价的 @abstractmethod
在基地 class.
这是它的样子:
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()
设为 class 方法而不是实例方法,因为它不依赖于具有特定数据的实例来知道什么是空的 str
/ bytes
看起来像.
此外,我们将 empty()
设为最终方法,因此 MyStr
或 MyBytes 的子 class 想要进一步提供特定行为的子 class 不会改变被认为是“空的”(因为只有一种东西可以被认为是空的)。
以上所有内容都将在 mypy --strict
下进行类型检查。
在调用方,他们永远不会实例化 MyObject[str]
或 MyObject[bytes]
(事实上,mypy
会阻止这种情况,正如我们希望的那样,因为 MyObject
不会'有 empty()
的实现)。相反,因为您在评论中说调用者会提前知道他们想要 bytes
还是 str
,所以他们会直接实例化 MyStr
或 MyBytes
。
我正在 AnyStr
上写一个通用的 class,所以允许 bytes
或 str
。
class MyObject(Generic[AnyStr]):
...
在此 class 的(多个)方法中,我想根据类型参数构造空字节或空字符串对象 b''
或 ''
。我该怎么做?
您应该有一个基础 class,其共享方法适用于 str
和 bytes
,它们利用共同的行为(例如,str
和bytes
具有长度,或者 str
和 bytes
都可索引),以及两个子 class 提供特定行为的实现。为了强制 subclasses 提供那些特定的行为(这样 mypy
可以假设调用它们的特定方法会在基础 class 中成功),你做一个等价的 @abstractmethod
在基地 class.
这是它的样子:
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()
设为 class 方法而不是实例方法,因为它不依赖于具有特定数据的实例来知道什么是空的 str
/ bytes
看起来像.
此外,我们将 empty()
设为最终方法,因此 MyStr
或 MyBytes 的子 class 想要进一步提供特定行为的子 class 不会改变被认为是“空的”(因为只有一种东西可以被认为是空的)。
以上所有内容都将在 mypy --strict
下进行类型检查。
在调用方,他们永远不会实例化 MyObject[str]
或 MyObject[bytes]
(事实上,mypy
会阻止这种情况,正如我们希望的那样,因为 MyObject
不会'有 empty()
的实现)。相反,因为您在评论中说调用者会提前知道他们想要 bytes
还是 str
,所以他们会直接实例化 MyStr
或 MyBytes
。