首页 > 解决方案 > 在抽象方法中使用子类类型的抽象基类

问题描述

我想用一个抽象方法创建一个抽象基类,该方法返回实现该接口的任何子类的实例。除了我在下面创建的方法之外,还有一种更 Python 的方法可以为 mypy 实现这一点吗?

在我的代码示例中,我将Animal类设为通用。子类可以从 Animal 继承并将泛型参数指定为自身,但对我来说这似乎很笨拙和错误。我想我可能遗漏了一些明显的东西。

请注意,在下面的代码中,当我Animal对类定义进行子类化时,使用类似Dog(Animal["Dog"]). 它对我来说看起来不正确,但它适用于类型检查。有没有办法为抽象方法指示它必须返回与 相同的类型self

import abc
from typing import Generic, TypeVar
from __future__ import annotations

T = TypeVar('T')

class Animal(abc.ABC, Generic[T]):

    @abc.abstractmethod
    def procreate(self: T, other: T) -> T:
        pass


class Dog(Animal["Dog"]):

    def procreate(self, other: "Dog"):
        return Dog()

class Cat(Animal["Cat"]):

    def procreate(self, other: "Cat"):
        return Cat()


dog = Dog()

dog.procreate(Cat())

标签: pythonabstract-classmypy

解决方案


AFAIK 你不需要你的Animal类,Generic除非它是某种容器,例如Sequence,我们可以只TypeVar用于特定的方法

所以这应该按预期工作

import abc
from typing import TypeVar
from __future__ import annotations

T = TypeVar('T')


class Animal(abc.ABC):
    @abc.abstractmethod
    def procreate(self: T, other: T) -> T:
        pass


class Dog(Animal):
    def procreate(self, other: "Dog") -> "Dog":
        return Dog()


class Cat(Animal):
    def procreate(self, other: "Cat") -> "Cat":
        return Cat()


dog = Dog()

dog.procreate(Cat())

mypy将在最后一行通知错误:

> mypy test.py
test.py:26: error: Argument 1 to "procreate" of "Dog" has incompatible type "Cat"; expected "Dog"
Found 1 error in 1 file (checked 1 source file)

推荐阅读