【问题标题】:TypeVar and assignment expresionTypeVar 和赋值表达式
【发布时间】:2022-08-03 22:36:54
【问题描述】:

我使用赋值表达式(又名海象运算符,在PEP 572 中定义)来定义类型T。这似乎是一个优雅的解决方案,但显然 mypy 不同意。

对于以下代码:

# Python 3.10.4

from collections.abc import Sequence
from typing import TypeVar

def foo(seq: Sequence[T := TypeVar(\'T\')]) -> T:
    return seq[0]

mypy 报告:

error: Invalid type comment or annotation
error: Name \"T\" is not defined

TypeVar 是否以某种方式禁止海象?

  • 那不是海象的用途-可读性付诸东流。也许 mypy 没有实现 walrus,因为它通常不会改变可读代码中的任何内容......?
  • mypy 是静态分析,它实际上并不执行您的代码。显然,在 TypeVar 的情况下,必须支持识别基本分配模式,但更复杂的形式不太可能起作用。这里还有一个注释peps.python.org/pep-0484/#generics\"TypeVar() 表达式必须始终直接分配给变量(不应用作更大表达式的一部分)。\"
  • @Anentropic 我认为这就是答案。感谢您的参考。有人可能会争辩说赋值表达式实际上是对变量的直接赋值;)

标签: python mypy python-typing


【解决方案1】:

这是真的馊主意。

假设您有未来导入的注释 - 那么这只是一个长字符串,不会发生分配。假设您想在函数体中使用cast(T, something)。如果mypy 接受这个,它会错过运行时错误:

NameError:名称“T”未定义

因此,在这种情况下,PEP563 会更改代码的行为。

from __future__ import annotations

from collections.abc import Sequence
from typing import TypeVar


def foo(seq: Sequence[T := TypeVar('T')]) -> T:
    return cast(T, seq[0])

你可以cast('T', ...) 代替,但这不是真正的注释情况。

【讨论】:

    【解决方案2】:

    从 python 3.12 开始(假设PEP695 被接受),可以使用更优雅、更强大的方括号语法来替换TypeVar

    from typing import Callable
    
    def func[**P, R](cb: Callable[P, R], *args: P.args, **kwargs: P.kwargs) -> R:
        ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-03
      • 1970-01-01
      • 1970-01-01
      • 2021-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多