mypy检查打字。与Python 3.7支持协议

发布于 2025-01-21 15:50:03 字数 1448 浏览 1 评论 0 原文

我有一个需要支持Python 3.7的项目,但是我想使用 typing.protocol ,在3.8中添加。为了支持3.7,我有一个较小的后备代码,该代码仅使用 object

import typing

_Protocol = getattr(typing, 'Protocol', object)

class Foo(_Protocol):
    def bar(self) -> int:
        pass

这一切正如我所期望的。问题是,在运行mypy时,我会收到以下错误:

test.py:5: error: Variable "test._Protocol" is not valid as a type
test.py:5: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
test.py:5: error: Invalid base class "_Protocol"

链接”变量vs类型别名该错误消息中的部分表示我应该注释 _protocol with :typing.type [object] 无效)或使用 typing.typealias (直到Python 3.9才能使用)。

如何向Mypy表示 _protocol 有效作为一种类型?


我尝试的另一个解决方法是在

if sys.version_info >= (3, 8):
    _Protocol = typing.Protocol
else:
    _Protocol = object

但是,这以相同的错误结束。

I have a project which needs to support Python 3.7, but I would like to use typing.Protocol, which was added in 3.8. To support 3.7, I have a minor bit of fallback code which just uses object:

import typing

_Protocol = getattr(typing, 'Protocol', object)

class Foo(_Protocol):
    def bar(self) -> int:
        pass

This all functions as I would expect. The issue is, when running MyPy, I get the following error:

test.py:5: error: Variable "test._Protocol" is not valid as a type
test.py:5: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
test.py:5: error: Invalid base class "_Protocol"

The linked "Variables vs type aliases" section in that error message indicates that I should annotate _Protocol with : typing.Type[object] (which does not work) or use typing.TypeAlias (which isn't available until Python 3.9).

How can I indicate to MyPy that _Protocol is valid as a type?


Another workaround I tried was in "Python version and system platform checks":

if sys.version_info >= (3, 8):
    _Protocol = typing.Protocol
else:
    _Protocol = object

However, this ends with the same error.

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

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

发布评论

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

评论(2

阿楠 2025-01-28 15:50:03

使用 typing_extensions typing.type_checking to Import typing_extensions 仅在键入键入代码时。

import typing

if typing.TYPE_CHECKING:
    from typing_extensions import Protocol
else:
    Protocol = object


class Foo(Protocol):
    def bar(self) -> int:
        ...

typing_extensions python版本并使用 typing.protocol 版本> = 3.8

# 3.8+
if hasattr(typing, 'Protocol'):
    Protocol = typing.Protocol
# 3.7
else:
    ...

Use typing_extensions and typing.TYPE_CHECKING to import typing_extensions only when type-checking the code.

import typing

if typing.TYPE_CHECKING:
    from typing_extensions import Protocol
else:
    Protocol = object


class Foo(Protocol):
    def bar(self) -> int:
        ...

typing_extensions checks the Python version and uses typing.Protocol for versions >=3.8:

# 3.8+
if hasattr(typing, 'Protocol'):
    Protocol = typing.Protocol
# 3.7
else:
    ...
水染的天色ゝ 2025-01-28 15:50:03

Mypy似乎可以正确理解协议作为导入语句的一部分:

if sys.version_info >= (3, 8):
    from typing import Protocol as _Protocol
else:
    _Protocol = object

class Foo(_Protocol):
    def bar(self) -> int: ...

Mypy仍然会标记 foo 作为Python 3.7中的类型规范,因此您需要使用类似的解决方法来使用它:

if sys.version_info >= (3, 8):
    _Foo = Foo
else:
    _Foo = typing.Any

def bar(x: _Foo):
    pass

值得注意的是,Mypy do 不了解更多聪明的东西,例如 _foo = foo = foo如果sys.version_info> =(3,8)否则打字.yany - 您必须使用简单的格式。

It seems that MyPy can properly understand Protocol as part of an import statement:

if sys.version_info >= (3, 8):
    from typing import Protocol as _Protocol
else:
    _Protocol = object

class Foo(_Protocol):
    def bar(self) -> int: ...

MyPy will still flag usage of Foo as a type specification in Python 3.7, so you need a similar workaround for using it:

if sys.version_info >= (3, 8):
    _Foo = Foo
else:
    _Foo = typing.Any

def bar(x: _Foo):
    pass

It's worth noting that MyPy does not understand more clever things like _Foo = Foo if sys.version_info >= (3, 8) else typing.Any -- you have to use the simple format.

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