Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python构建复杂的mypy类型_Python_Python 3.x_Mypy - Fatal编程技术网

Python构建复杂的mypy类型

Python构建复杂的mypy类型,python,python-3.x,mypy,Python,Python 3.x,Mypy,在一个完美的世界里,我可以这样做: ScoreBaseType = Union[bool, int, float] ScoreComplexType = Union[ScoreBaseType, Dict[str, ScoreBaseType]] 但是,这意味着ScoreComplexType要么是ScoreBaseType,要么是允许多种类型值的字典。。。不是我想要的 以下内容对我来说似乎应该有效,但实际上不行: ScoreBaseTypeList = [bool, int, float]

在一个完美的世界里,我可以这样做:

ScoreBaseType = Union[bool, int, float]
ScoreComplexType = Union[ScoreBaseType, Dict[str, ScoreBaseType]]
但是,这意味着ScoreComplexType要么是ScoreBaseType,要么是允许多种类型值的字典。。。不是我想要的

以下内容对我来说似乎应该有效,但实际上不行:

ScoreBaseTypeList = [bool, int, float]
ScoreBaseType = Union[*ScoreBaseTypeList]  # pycharm says "can't use starred expression here"
ScoreDictType = reduce(lambda lhs,rhs: Union[lhs, rhs], map(lambda x: Dict[str, x], ScoreBaseTypeList))
ScoreComplexType = Union[ScoreBaseType, ScoreDictType]
有没有什么方法可以让我不必经历这种单调乏味的事情就可以做上述的事情

ScoreComplexType = Union[bool, int, float,
                     Dict[str, bool],
                     Dict[str, int],
                     Dict[str, float]]
编辑:更充实的所需用法示例:

# these strings are completely arbitrary and determined at runtime. Used as keys in nested dictionaries.
CatalogStr = NewType('CatalogStr', str)
DatasetStr = NewType('DatasetStr', str)
ScoreTypeStr = NewType('ScoreTypeStr', str)

ScoreBaseType = Union[bool, int, float]
ScoreDictType = Dict[ScoreTypeStr, 'ScoreBaseTypeVar']
ScoreComplexType = Union['ScoreBaseTypeVar', ScoreDictType]

ScoreBaseTypeVar = TypeVar('ScoreBaseTypeVar', bound=ScoreBaseType)
ScoreComplexTypeVar = TypeVar('ScoreComplexTypeVar', bound=ScoreComplexType) # errors: "constraints cannot be parameterized by type variables"

class EvalBase(ABC, Generic[ScoreComplexTypeVar]):
    def __init__(self) -> None:
        self.scores: Dict[CatalogStr,
                          Dict[DatasetStr,
                               ScoreComplexTypeVar]
                          ] = {}

class EvalExample(EvalBase[Dict[float]]): # can't do this either
    ...
编辑2: 我突然想到,如果我使用元组而不是嵌套字典,我可以简化很多类型暗示。这可能有用吗?我只在下面的玩具示例中尝试了它,还没有尝试修改我的所有代码

# These are used to make typing hints easier to understand
CatalogStr = NewType('CatalogStr', str)  # A str corresponding to the name of a catalog
DatasetStr = NewType('DatasetStr', str)  # A str corresponding to the name of a dataset
ScoreTypeStr = NewType('ScoreTypeStr', str)  # A str corresponding to the label for a ScoreType

ScoreBaseType = Union[bool, int, float]

SimpleScoreDictKey = Tuple[CatalogStr, DatasetStr]
ComplexScoreDictKey = Tuple[CatalogStr, DatasetStr, ScoreTypeStr]
ScoreKey = Union[SimpleScoreDictKey, ComplexScoreDictKey]
ScoreKeyTypeVar = TypeVar('ScoreKeyTypeVar', bound=ScoreKey)
ScoreDictType = Dict[ScoreKey, ScoreBaseType]

# These are used for Generics in classes
DatasetTypeVar = TypeVar('DatasetTypeVar', bound='Dataset')  # Must match a type inherited from Dataset
ScoreBaseTypeVar = TypeVar('ScoreBaseTypeVar', bound=ScoreBaseType)


class EvalBase(ABC, Generic[ScoreBaseTypeVar, ScoreKeyTypeVar]):
    def __init__(self):
        self.score: ScoreDictType = {}


class EvalExample(EvalBase[float, ComplexScoreDictKey]):
    ...
尽管如此,这会是什么样的结果呢?似乎我可能需要存储一些键列表才能进行迭代

for catalog_name in self.catalog_list:
    for dataset_name in self.scores[catalog_name]:
        for score in self.scores[catalog_name][dataset_name]:

您可能需要使用TypeVars来表达这一点,但是如果没有示例说明您打算如何使用它,就很难说了

这将如何用于键入依赖于输入的返回值的示例:

ScoreBaseType=Union[bool,int,float]
ScoreTypeVar=TypeVar('ScoreTypeVar',bound=ScoreBaseType)
ScoreDictType=Union[ScoreTypeVar,Dict[str,ScoreTypeVar]]
def scoring_func(Iterable[ScoreTypeVar])->ScoreDictType:
...
如果您不是基于输入值来执行此操作,那么您可能需要

ScoreBaseType=Union[bool,int,float]
ScoreDictTypes=Union[Dict[str,bool],Dict[str,int],Dict[str,float]]
ScoreComplexType=联合[ScoreBaseType,ScoreDictTypes]
根据您处理类型的方式,您还可以使用
SupportsInt
SupportsFloat
类型,而不是同时使用
int
float

编辑:(基于下面编辑的OP的其他信息)

由于您正在使用此命令键入ABC,因此使用
Dict[str,Any]
键入基类并进一步约束子类就足够了

如果不是,您将拥有非常详细的类型定义,并且没有太多的替代方案,就像mypy目前所拥有的那样,即使在对常量进行操作时也是如此


mypy目前还不支持递归类型别名(,它是),因此为了可读性,您需要为每个潜在嵌套级别定义允许的类型,然后将它们收集到表示完整嵌套结构的类型中。

感谢您的响应!修改了我原来的帖子,给出了一个更加充实的用法示例。特别是,我有几个嵌套字典(ick)。它可能是
Dict[str,Dict[str,Union[bool,int,float]
Dict[str,Dict[str,Union[bool,int,float]]
,取决于子类。我已经更新了我的答案,以反映您的编辑,但这可能更多的是确认缺少的功能以及如何处理它,而不是简单的修复。我进行了另一次编辑…您对元组方法(相对于三重嵌套字典)有何看法?在一个玩具示例中,它似乎超过了mypy,但我不想花时间重构一堆代码,结果却发现了一个我没有想到的小问题。我认为我对您的代码了解不够,无法对设计提出具体建议。字典和元组有不同的优缺点,因此切换数据类型可能会导致我的更改n性能。