Python 中使用 returns 包的嵌套泛型

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

举个例子,我有一个动物园。动物园 (Z) 有笼子列表 (C),笼子有动物列表 (A)。

由于 mypy 不正确支持嵌套泛型,我正在尝试使用 returns 包的更高种类类型以获得正确的类型检查。

作为一种特殊类型的动物园,我有一个 OpenZoo,它只能包含带有狗的 OpenCages。

我的尝试看起来像这样:

import itertools

from typing import TypeVar

from returns.primitives.hkt import Kind1, Kind2, SupportsKind1, SupportsKind2

A = TypeVar('A', bound='Animal')
C = TypeVar('C', bound='Cage')
Z = TypeVar('Z', bound='Zoo')

class Animal:

    def feed(self):
        ...

class Dog(Animal):

    def bark(self):
        print("Woof!")

class Cage(SupportsKind1['Cage', A]):
    def __init__(self, animals: list[A]):
        self.animals = animals


class OpenCage(Cage[Dog]):
    def unleash(self) -> None:
        ...

class Zoo(SupportsKind2['Zoo', C, A]):

    def __init__(self, cages: list[Kind1[C, A]]):
        self.cages = cages

    def all_animals(self) -> list[A]:
        return list(itertools.chain.from_iterable([c.animals for c in iter(self.cages)]))


class OpenZoo(Zoo[OpenCage, Dog]):
    def unlock_cages(self) -> None:
        ...


my_animal = Dog()
my_cage = OpenCage([my_animal])
my_zoo = OpenZoo([my_cage]) # <--- mypy error here

但是,这会产生 mypy 错误

error: List item 0 has incompatible type "OpenCage"; expected "KindN[OpenCage, Dog, Any, Any]"  [list-item]

知道我应该如何解决这个问题吗?或者是否有另一种(更好)的方法来实现这一目标?

我正在使用 python 3.10 和 mypy 1.0.1

python python-typing mypy
1个回答
1
投票

我做了一些研究,发现了这个:

错误消息表明 my_cage 的类型是 OpenCage,与 OpenZoo 的第二个类型参数的预期类型 KindN[OpenCage, Dog, Any, Any] 不兼容。

这是因为 OpenZoo 被定义为仅包含 OpenCage 且动物类型为 Dog 的动物园,但 my_cage 的类型仅为 OpenCage[Dog]。因此,需要使用 SupportsKind1 将 my_cage 的类型提升为 Kind1[OpenCage, Dog],以匹配 Zoo 的类型参数。

下面的代码应该可以解决该错误

import itertools
    
from typing import TypeVar

A = TypeVar('A', bound='Animal')
C = TypeVar('C', bound='Cage')
Z = TypeVar('Z', bound=Zoo[C, A])

class Animal:
    def feed(self):
        ...

class Dog(Animal):
    def bark(self):
        print("Woof!")

class Cage:
    def __init__(self, animals: list[A]):
        self.animals = animals

class OpenCage(Cage):
    def unleash(self) -> None:
        ...

class Zoo:
    def __init__(self, cages: list[Cage]):
        self.cages = cages

    def all_animals(self) -> list[A]:
        return [animal for cage in self.cages for animal in cage.animals]

class OpenZoo(Zoo):
    def unlock_cages(self) -> None:
        ...

my_animal = Dog()
my_cage = OpenCage([my_animal])
my_zoo = OpenZoo([my_cage])

希望这有帮助:)

© www.soinside.com 2019 - 2024. All rights reserved.