我讨厌写两次东西,所以我想出了一个不错的方法来不必写两次东西。然而,这似乎打破了我的类型提示:
from enum import Enum
from dataclasses import make_dataclass, field, dataclass
class DatasetNames(Enum):
test1 = "test1_string"
test2 = "test2_string"
test3 = "test3_string"
def get_path(s: str) -> str:
return s + "_path"
# the normal way to do this, but I have to type every new dataset name twice
# and there's a lot of duplicate code
@dataclass(frozen=True)
class StaticDatasetPaths:
test1 = get_path("test1_string")
test2 = get_path("test2_string")
test3 = get_path("test3_string")
# mypy recognizes that `StaticDatasetPaths` is a class
# mypy recognizes that `StaticDatasetPaths.test2` is a string
print(StaticDatasetPaths.test2) # 'test2_string_path'
# this is my way of doing it, without having to type every new dataset name twice and no duplicate code
DynamicDatasetPaths = make_dataclass(
'DynamicDatasetPaths',
[
(
name.name,
str,
field(default=get_path(name.value))
)
for name in DatasetNames
],
frozen=True
)
# mypy thinks `DynamicDatasetPaths` is a `variable` of type `type`
# mypy thinks that `DynamicDatasetPaths.test2` is an `function` of type `Unknown`
print(DynamicDatasetPaths.test2) # 'test2_string_path'
如何让mypy知道DynamicDatasetPaths是一个属性为字符串的冻结数据类?
通常,当我遇到这样的情况时,我可以只使用
cast
并告诉 mypy 正确的类型是什么,但我不知道“属性为字符串的冻结数据类”的正确类型。
(另外,如果有更好的方法来避免重复的代码,我也很高兴听到这一点。)
数据类旨在创建实例。由于您不是实例化数据类,而是访问
test1
、test2
等作为类属性,因此您可以简单地将 get_path
设为 Enum
类的方法:
from enum import Enum
class DatasetNames(Enum):
test1 = "test1_string"
test2 = "test2_string"
test3 = "test3_string"
def get_path(self) -> str:
return self.value + '_path'
print(DatasetNames.test2.get_path()) # outputs test2_string_path