微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 Python 类型的 TypeVar 进行带绑定的通用类型返回

如何解决使用 Python 类型的 TypeVar 进行带绑定的通用类型返回

当尝试使用键入的 TypeVar 来启用具有返回类型的泛型时,我遇到了一个 mypy 错误,即在比较字典类型和预期返回时未考虑 bound 参数函数类型。

以下是我面临的情况的示例:

from typing import Dict,List,Type,TypeVar


class Bird:
    def call(self):
        print(self.sound)


class Chicken(Bird):
    def __init__(self):
        self.sound = "bok bok"


class Owl(Bird):
    def __init__(self):
        self.sound = "hoot hoot"


T = TypeVar("T",bound=Bird)


class Instantiator:
    def __init__(self,birds: List[Type[Bird]]):
        self._bird_map: Dict[Type[Bird],Bird] = {}
        for bird in birds:
            self._bird_map[bird] = bird()

    def get_bird(self,bird_type: Type[T]) -> T:
        return self._bird_map[bird_type]

运行 mypy 验证器将显示temp.py:29: error: Incompatible return value type (got "Bird",expected "T")

Instantiator 用作一种“跟踪器”,用于实例化每种鸟类中的一种。当尝试根据类类型检索实例化对象时,这就是为什么需要使用泛型的原因,否则以后键入的字段会抱怨使用 Bird 类而不是 Chicken 或 {{ 之一1}}。

在这里错误地使用了 Owl 吗?有没有不同的方法来处理结构?这是 mypy 的疏忽吗?

解决方法

这是因为您定义了一个仅包含基类对象 Bird 的字典,但是在函数 get_bird 中,您试图返回基类类型的对象,而派生类可能是预期的。 Mypy 不会使 Base -> Derived 投射。

您可以使 __init__ 也成为通用函数。

T = TypeVar("T",bound=Bird)

class Instantiator():
    def __init__(self,birds: List[Type[T]]):
        self._bird_map: Dict[Type[T],T] = {}
        for bird in birds:
            self._bird_map[bird] = bird()

    def get_bird(self,bird_type: Type[T]) -> T:
        return self._bird_map[bird_type]

或者明确使用 cast:

class Instantiator:
    def __init__(self,birds: List[Type[Bird]]):
        self._bird_map: Dict[Type[Bird],Bird] = {}
        for bird in birds:
            self._bird_map[bird] = bird()

    def get_bird(self,bird_type: Type[T]) -> T:
        return cast(T,self._bird_map[bird_type])  

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。