输入通用(协议)类参数的注释

发布于 2025-01-27 10:29:42 字数 1450 浏览 0 评论 0原文

我正在尝试计算如何为应该是实现通用协议的类函数参数添加类型注释。

例如,假设我有一个可以看起来像这样的集合的协议:

from typing import (
    Protocol, TypeVar, Iterable
)

T = TypeVar('T', contravariant=True)


class Set(Protocol[T]):
    """A set of elements of type T."""

    def __init__(self, init: Iterable[T]) -> None:
        """Initialise set with init."""
        ...

    def __contains__(self, x: T) -> bool:
        """Test if x is in set."""
        ...

    def add(self, x: T) -> None:
        """Add x to the set."""
        ...

    def remove(self, x: T) -> None:
        """Remove x from the set."""
        ...

并且我有一种使用各种类型集的算法,我想通过设置实现来参数。为简单起见,我将在此功能中创建一个列表以用作示例:

from typing import Type

def foo(set_type: Type[Set]) -> None:
    """Do clever stuff."""
    x = list(range(10))
    s = set_type(x)
    ...

mypy告诉我set缺少一个类型参数,我想是正确的,但我不想给它一个,因为我打算使用不同类型的set_type

如果我给出set a typevar而是

def foo(set_type: Type[Set[T]]) -> None:
    """Do clever stuff"""
    x = list(range(10))
    s = set_type(x)
    ...

得到我的警告:i set_type()获得不兼容的类型,list> list [int]而不是itoble [t],这又是正确的,但对我没有太大帮助。

有没有办法指定我的函数参数可以用作不同类型集的通用构造函数?

I'm trying to work out how to add a type annotation for a function argument that should be a class implementing a generic protocol.

As an example, assume I have a protocol for a set that could look something like this:

from typing import (
    Protocol, TypeVar, Iterable
)

T = TypeVar('T', contravariant=True)


class Set(Protocol[T]):
    """A set of elements of type T."""

    def __init__(self, init: Iterable[T]) -> None:
        """Initialise set with init."""
        ...

    def __contains__(self, x: T) -> bool:
        """Test if x is in set."""
        ...

    def add(self, x: T) -> None:
        """Add x to the set."""
        ...

    def remove(self, x: T) -> None:
        """Remove x from the set."""
        ...

and I have an algorithm that uses sets of various types, that I want to parameterise with the set implementation. For simplicity I'll just create a list in this function to use as an example:

from typing import Type

def foo(set_type: Type[Set]) -> None:
    """Do clever stuff."""
    x = list(range(10))
    s = set_type(x)
    ...

Here, mypy tells me that Set is missing a type parameter, which I suppose is correct, but I don't want to give it one, as I plan to use set_type with different types.

If I give Set a TypeVar instead

def foo(set_type: Type[Set[T]]) -> None:
    """Do clever stuff"""
    x = list(range(10))
    s = set_type(x)
    ...

I instead get the warning that I set_type() gets an incompatible type, List[int] instead of Iterable[T], which again is correct, but doesn't help me much.

Is there a way to specify that my function argument can be used as a generic constructor for sets of different types?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蛮可爱 2025-02-03 10:29:42

协议什么也没说__ Init __的签名,即使它是在协议上定义的。 type做类似的事情 - 即使set不是协议type [set]什么也没说如何调用类型。

我最初建议使用callable [[iTable [t]],set [t]]。但是,这是有问题的,并且仅是因为我省略了通用参数,从本质上讲,它使其成为>任何,如这个github问题。您可以使用(而不是冗长)协议。

class MkSet(Protocol):
    def __call__(self, it: Iterable[T]) -> Set[T]:
        ...

def foo(set_type: MkSet) -> None:
    ...

Protocol says nothing about the signature of __init__, even if it's defined on the Protocol. Type does a similar thing - even if Set isn't a Protocol, Type[Set] says nothing about how the type is called.

I initially suggested using Callable[[Iterable[T]], Set[T]]. However, this is problematic, and only works because I omitted the generic parameter, essentially making it Any, as discussed in this Github issue. You can instead use a (rather verbose) protocol.

class MkSet(Protocol):
    def __call__(self, it: Iterable[T]) -> Set[T]:
        ...

def foo(set_type: MkSet) -> None:
    ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文