如何输入提示抽象方法属性并使 mypy 满意?

问题描述 投票:0回答:1

重写这个问题,因为事实证明我认为的问题并不是问题。事实上,我有一个看似相同的情况,mypy 并没有抱怨。

这是一个没有看似等效的 mypy 投诉的示例:

class TableLoader(ABC):
    @property
    @abstractmethod
    def FieldToDataHeaderKey(self):
        # dict of model dicts of field names and header keys
        pass

    def set_headers(self, custom_headers=None):
        for mdl in self.FieldToDataHeaderKey.keys():

class StudyTableLoader(TableLoader):
    FieldToDataHeaderKey = {
        Study.__name__: {
            "code": CODE_KEY,
            "name": NAME_KEY,
            "description": DESC_KEY,
        },
    }

但是,这个看似等效的代码会产生 mypy 错误:

class PeakAnnotationsLoader(ABC):
    @property
    @abstractmethod
    def add_columns_dict(self):
        pass

    @classmethod
    def add_df_columns(cls, df_dict: dict):
        for sheet, column_dict in cls.add_columns_dict.items():
            # ^^^ This is the line that produces the error
            ...

class IsocorrLoader(PeakAnnotationsLoader):
    add_columns_dict = {}

mypy
产生以下错误:

DataRepo/loaders/peak_annotations_loader.py:213: error: "Callable[[PeakAnnotationsLoader], Any]" has no attribute "items"  [attr-defined]
DataRepo/loaders/peak_annotations_loader.py:321: error: Need type annotation for "add_columns_dict" (hint: "add_columns_dict: Dict[<type>, <type>] = ...")  [var-annotated]

我不知道如何在第二种情况下让我的朋友开心。顺便说一句,所有这些代码都有效。我如何在这里满足我的要求?

我应该有不同的方式来创建抽象类属性吗?我有多个继承自

TableLoader
的类,并且它们都不会产生 mypy 错误 WRT
FieldToDataHeaderKey
。难道只是 mypy 没有像处理
.items()
那样处理
.keys()

python types mypy
1个回答
0
投票

PeakAnnotationsLoader
类中,
add_columns_dict
方法位于实例级别,而
add_df_columns
方法位于类级别。使用
cls.add_columns_dict
就像使用
PeakAnnotationsLoaderChildClass.add_columns_dict
一样,理论上返回 mypy 所说的返回值,一个可调用的。

代码之所以有效,是因为您重写了

add_columns_dict
方法并将其设为静态字段,因此
PeakAnnotationsLoaderChildClass.add_columns_dict
返回该字段的值。父类不会以任何方式强制子类覆盖
add_columns_dict
,因此 mypy 会抛出此错误。

如果通过删除

add_columns_dict
注释使
@classmethod
方法成为实例级方法,该错误就会消失。

覆盖抽象属性的预期方法如下:

class IsocorrLoader(PeakAnnotationsLoader):
  @property
  def add_columns_dict(self) -> Optional[Dict[str, Dict[str, function]]]:
    ...

这会破坏你的代码,并且它不再起作用,因为你不再将

add_columns_dict
设为类的静态字段。

根据我目前的知识,不可能有一个抽象类方法同时也是一个属性。

使

add_columns_dict
成为抽象类方法而不是抽象属性也可以使此错误消失。您的代码可能如下所示:

class PeakAnnotationsLoader(ABC):
    @classmethod
    @abstractmethod
    def get_add_columns_dict(self) -> Optional[Dict[str, Dict[str, function]]]:
        pass

    @classmethod
    def add_df_columns(cls, df_dict: dict):
        add_columns_dict = cls.get_add_columns_dict()
        if add_columns_dict is not None:
            for sheet, column_dict in add_columns_dict.items():
                ...

class IsocorrLoader(PeakAnnotationsLoader):
    @classmethod
    def get_add_columns_dict(self) -> Optional[Dict[str, Dict[str, function]]]:
        ...
© www.soinside.com 2019 - 2024. All rights reserved.