【问题标题】:Why does mypy complain about Any as return annotation and how should I annotate a return value that can be anything?为什么 mypy 抱怨 Any 作为返回注释,我应该如何注释可以是任何东西的返回值?
【发布时间】:2023-04-02 10:49:01
【问题描述】:

我有一个类,它本质上是一个字典的包装器:

class Wrapper(dict):

    ...

    def __getitem__(self, item: Hashable) -> Any:
        return self.wrapped[item]

使用mypy 检查注释时,检查此代码时会产生Explicit "Any" is not allowed。我的猜测是,这源于Any 是所有其他类型的祖先和继承者的概念。我应该如何注释这样的函数,我想允许返回任何东西?

【问题讨论】:

  • 我猜他们希望你只删除注释,但我仍然感到惊讶的是,明确的 Any 实际上会被禁止。
  • 另外,您似乎犯了一个常见的错误,即从dict 继承另一个 dict 作为实例变量。不要那样做;选择其中一个,否则您最终会浪费空间并遇到非常令人困惑的错误,即当您期望数据落在另一个字典中时,数据最终会出现在一个字典中。

标签: python types mypy


【解决方案1】:

您在问题中提供的信息不足,无法重现此错误,但如果您的唯一问题是:

我应该如何在我想要允许返回任何东西的地方注释这样的函数?

简单的答案是根本不要注释。默认情况下,它将充当Any

【讨论】:

  • 这真的是答案吗?我试过了,但现在我得到 “函数缺少一个或多个参数的类型注释 [no-untyped-def]”。这两个配置选项是互斥的,还是我遗漏了什么?我尝试使用object 进行注释,它似乎有效。
【解决方案2】:

如果您真的需要自定义映射(是吗?)我建议不要从 dict 继承,因为它可能会在未来造成很多痛苦(您应该重新定义它的方法,否则有时您会使用self.wrapped,有时不使用)。

我们可以简单地使用collections.abc module 中的MutableMapping ABC 并定义基本方法(如__getitem__),其余的(keys()valuesitems() 已定义)。

关于mypy:我更喜欢为元素/键/值/等定义辅助类型变量。在类内。

所以我们最终可以得到类似的东西

from collections import abc
from typing import (Dict,
                    Iterator,
                    TypeVar)


class Wrapper(abc.MutableMapping):
    KeyType = TypeVar('KeyType')
    ValueType = TypeVar('ValueType')

    def __init__(self, wrapped: Dict[KeyType, ValueType]) -> None:
        self.wrapped = wrapped

    def __delitem__(self, key: KeyType) -> None:
        del self.wrapped[key]

    def __len__(self) -> int:
        return len(self.wrapped)

    def __iter__(self) -> Iterator[KeyType]:
        return iter(self.wrapped)

    def __setitem__(self, key: KeyType, value: ValueType) -> None:
        self.wrapped[key] = value

    def __getitem__(self, key: KeyType) -> ValueType:
        return self.wrapped[key]

测试

使用--disallow-any-explicit 标志运行mypy 不会导致错误/警告。

【讨论】:

    【解决方案3】:

    该案例的正确注释是object,而不是AnyAny 完全是松散的;它可以表示任何类型的任何类型或任何子类型。所以要明确地说“这个值真的可以是 any 类型”,你使用所有对象的祖先:object。这在此处的文档中有所介绍:Dynamically typed code(尤其是 § Any vs. object)。

    附注我对类型理论很陌生,所以对此持保留态度。如果我有任何错误,任何反馈都非常感谢。我只是在回答,因为现有的答案没有涵盖为什么会发生错误或如何实际修复它而不是忽略它。

    【讨论】:

      【解决方案4】:

      当配置文件中该模块的disallow_any_explicit 设置为True 时,会发生这种情况。只需删除默认 False 的该选项即可。

      【讨论】:

      • 这会消除错误,但不能解决问题。我发布了my own answer,我认为这是实际的解决方案。
      猜你喜欢
      • 2015-05-17
      • 1970-01-01
      • 2020-06-25
      • 2021-07-03
      • 1970-01-01
      • 2020-07-24
      • 1970-01-01
      • 2022-01-12
      相关资源
      最近更新 更多