在Python中使用returns包的嵌套泛型

huangapple go评论70阅读模式
英文:

Nested generics in python using the returns package

问题

以下是代码的翻译部分:

作为示例我有一个动物园一个动物园Z有一个笼子列表C),而一个笼子有一个动物列表A)。

由于mypy不支持嵌套泛型我正在尝试使用[returns](https://returns.readthedocs.io/en/latest/)包的高级类型来获得正确的类型检查

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

我的尝试看起来像这样

```python
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错误在这里

然而,这会导致mypy错误 error: List item 0 has incompatible type "OpenCage"; expected "KindN[OpenCage, Dog, Any, Any]" [list-item]

你有任何解决此问题的想法吗?或者是否有另一种更好的方法来实现这一目标?

我正在使用Python 3.10和mypy 1.0.1。

英文:

As an example, I have a zoo. A zoo (Z) has a list of cages (C), and a cage has a list of animals (A).

Since mypy doesnt support nested generics properly, I am experimenting with the returns package's higher kinded types in order to get proper typechecks.

As a special type of zoo, I have an OpenZoo which can only contain OpenCages with Dogs in it.

My attempt looks like so:

import itertools

from typing import TypeVar

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

A = TypeVar(&#39;A&#39;, bound=&#39;Animal&#39;)
C = TypeVar(&#39;C&#39;, bound=&#39;Cage&#39;)
Z = TypeVar(&#39;Z&#39;, bound=&#39;Zoo&#39;)

class Animal:

	def feed(self):
		...

class Dog(Animal):

	def bark(self):
		print(&quot;Woof!&quot;)

class Cage(SupportsKind1[&#39;Cage&#39;, A]):
	def __init__(self, animals: list[A]):
		self.animals = animals


class OpenCage(Cage[Dog]):
	def unleash(self) -&gt; None:
		...

class Zoo(SupportsKind2[&#39;Zoo&#39;, C, A]):

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

	def all_animals(self) -&gt; 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) -&gt; None:
		...


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

However, this yields mypy error error: List item 0 has incompatible type &quot;OpenCage&quot;; expected &quot;KindN[OpenCage, Dog, Any, Any]&quot; [list-item]

Any idea how I should fix this issue? Or if there is another (better) way of achieving this?

I'm using python 3.10 and mypy 1.0.1

答案1

得分: 0

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

这是因为OpenZoo被定义为只包含具有Dog作为动物类型的OpenCage的动物园,但my_cage的类型仅为OpenCage[Dog]。因此,my_cage的类型需要使用SupportsKind1提升为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])

希望对你有所帮助 在Python中使用returns包的嵌套泛型

英文:

I did some research and i found this :

The error message suggests that the type of my_cage is OpenCage, which is not compatible with the expected type of KindN[OpenCage, Dog, Any, Any] for the second type parameter of OpenZoo.

This is because OpenZoo is defined as a Zoo that only contains OpenCage with Dog as the animal type, but my_cage is of type OpenCage[Dog] only. Therefore, the type of my_cage needs to be lifted to a Kind1[OpenCage, Dog] using SupportsKind1 in order to match the type parameter of Zoo.

The code below should resolve the error

import itertools
    
from typing import TypeVar

A = TypeVar(&#39;A&#39;, bound=&#39;Animal&#39;)
C = TypeVar(&#39;C&#39;, bound=&#39;Cage&#39;)
Z = TypeVar(&#39;Z&#39;, bound=Zoo[C, A])

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

class Dog(Animal):
    def bark(self):
        print(&quot;Woof!&quot;)

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

class OpenCage(Cage):
    def unleash(self) -&gt; None:
        ...

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

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

class OpenZoo(Zoo):
    def unlock_cages(self) -&gt; None:
        ...

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

Hope this helps 在Python中使用returns包的嵌套泛型

huangapple
  • 本文由 发表于 2023年2月23日 22:49:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75546419.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定