小编Ale*_*ood的帖子

Python 静态类型提示/检查 Iterable[AnyStr] 与 Iterable[str] 之间的不匹配 | 可迭代[字节]

我遇到了这个静态类型提示不匹配(使用 Pyright):

from __future__ import annotations
from typing import AnyStr, Iterable


def foo(i: Iterable[AnyStr]):
    return i


def bar(i: Iterable[str] | Iterable[bytes]):
    return i


def baz(i: Iterable[str | bytes]):
    return i


def main():
    s = ['a']

    # makes sense to me
    baz(foo(s))  # allowed
    foo(baz(s))  # not allowed

    # makes sense to me
    baz(bar(s))  # allowed
    bar(baz(s))  # not allowed

    bar(foo(s))  # allowed
    foo(bar(s))  # nope -- why?
Run Code Online (Sandbox Code Playgroud)

什么之间的区别Iterable[AnyStr]Iterable[str] | Iterable[bytes]

它们不应该是“等效的”吗?(除了AnyStr在上下文中引用单个一致类型)

更具体地说:键入提示以下内容的正确方法是什么?

import random …
Run Code Online (Sandbox Code Playgroud)

python covariance contravariance type-hinting python-typing

5
推荐指数
1
解决办法
61
查看次数

正则表达式匹配“|” 联合类型的分隔值

我正在尝试匹配类型注释,例如int | str,并使用正则表达式替换将它们替换为 string Union[int, str]

期望的替换(之前和之后):

  • str|int|bool->Union[str,int,bool]
  • Optional[int|tuple[str|int]]->Optional[Union[int,tuple[Union[str,int]]]]
  • dict[str | int, list[B | C | Optional[D]]]->dict[Union[str,int], list[Union[B,C,Optional[D]]]]

到目前为止我想出的正则表达式如下:

r"\w*(?:\[|,|^)[\t ]*((?'type'[a-zA-Z0-9_.\[\]]+)(?:[\t ]*\|[\t ]*(?&type))+)(?:\]|,|$)"
Run Code Online (Sandbox Code Playgroud)

您可以在 Regex Demo 上尝试一下。它并没有真正按照我想要的方式工作。到目前为止我注意到的问题:

  • 到目前为止,它似乎无法处理嵌套的 Union 条件。例如,int | tuple[str|int] | bool似乎会导致一场匹配,而不是两次匹配(包括内部 Union 条件)。

  • 正则表达式似乎]最后消耗了不必要的东西。

  • 可能是最重要的一个,但我注意到 Python 中的模块似乎不支持正则表达式子例程re是我想到使用它的地方。

附加信息

这主要是为了支持Python 3.7+ 的PEP 604语法,该语法需要前向声明(例如声明为字符串)注释才能支持,否则内置类型不支持该|运算符。

这是我想出的示例代码:

r"\w*(?:\[|,|^)[\t ]*((?'type'[a-zA-Z0-9_.\[\]]+)(?:[\t ]*\|[\t ]*(?&type))+)(?:\]|,|$)"
Run Code Online (Sandbox Code Playgroud)

对于 3.10 之前的 Python 版本,我使用__future__import 来避免出现以下错误: …

python regex annotations python-3.x python-typing

5
推荐指数
1
解决办法
946
查看次数

为什么当 mypy 需要类型注释时,愚蠢的注释会处理错误?

Mypy 在这一行出错:

response = {'available_fields': []}

error: Need type annotation for 'response'
Run Code Online (Sandbox Code Playgroud)

当我添加响应是字典的愚蠢注释时,错误消失了:

response: typing.Dict = {'available_fields': []}
Run Code Online (Sandbox Code Playgroud)

所以,我对此有一些疑问。为什么愚蠢的注释会处理错误?如何调整 mypy(配置、选项等)而不担心没有注释的这一行?

python annotations type-hinting mypy python-typing

4
推荐指数
1
解决办法
1万
查看次数

如何使用静态检查来确保对象具有特定的方法/属性?

Is there I way that I can annotate a function to ensure that an object being passed into the function has a certain method or attribute, but where I don't care about its actual type?

Pycharm internally uses a syntax that looks like {b} to indicate what methods/attributes it's inferred are required for the object, but that doesn't appear to be valid Python syntax:

def func(a: {b}):  # Error
    a.b = 1
Run Code Online (Sandbox Code Playgroud)

Is there a way to get the type …

python duck-typing type-hinting python-3.x python-typing

4
推荐指数
1
解决办法
723
查看次数

对元组进行类型提示但又不会太冗长

有没有一种方法可以输入提示元素元组,而不必多次定义每个内部元素?

例子:

a = ((1, 2), (2, 3), (3, 4), (4, 5))

a: Tuple[Tuple[int, int], Tuple[int, int], Tuple[int, int], Tuple[int, int]]
Run Code Online (Sandbox Code Playgroud)

我正在寻找看起来像这样的东西

a: Tuple[5*Tuple[int, int]]
Run Code Online (Sandbox Code Playgroud)

否则我的代码会变得非常冗长,以便指示类似的内容(包含 5 个 4 个整数的元组的元组)

python type-hinting python-typing

4
推荐指数
1
解决办法
1606
查看次数

对于具有“@”(矩阵乘法)的对象的 Python 类型提示

我有一个函数fun()接受 NumPy ArrayLike和“矩阵”,并返回 numpy 数组。

from numpy.typing import ArrayLike
import numpy as np

def fun(A, x: ArrayLike) -> np.ndarray:
    return (A @ x) ** 2 - 27.0
Run Code Online (Sandbox Code Playgroud)

type对于有业务的实体,正确的是什么@?请注意,fun()也可以接受scipy.sparse;也许更多。

python numpy type-hinting python-typing

4
推荐指数
1
解决办法
313
查看次数

Mypy 在 __init__ 覆盖中接受不兼容的类型

我有以下Foo基类,并且Bar继承自它:

class Foo:
    def __init__(self, x: int) -> None:
        self._x = x

    def do(self, x: int) -> None:
        pass


class Bar(Foo):
    pass
Run Code Online (Sandbox Code Playgroud)

如果我重写Foo.doin Bar,并将参数的类型更改x为不兼容的内容(即不比 更通用int),那么 Mypy 将返回错误 - 这当然是我所期望的。

class Bar(Foo):
    def do(self, x: str) -> None:
        pass
Run Code Online (Sandbox Code Playgroud)

错误:

test.py:10: error: Argument 1 of "do" is incompatible with supertype "Foo"; supertype defines the argument type as "int"
test.py:10: note: This violates the Liskov substitution principle
test.py:10: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides …
Run Code Online (Sandbox Code Playgroud)

python types liskov-substitution-principle mypy python-typing

4
推荐指数
1
解决办法
1111
查看次数

如何使用Python中元类插入的方法对类进行类型检查?

在以下代码中some_method已通过元类添加:

from abc import ABC
from abc import ABCMeta
from typing import Type


def some_method(cls, x: str) -> str:
    return f"result {x}"


class MyMeta(ABCMeta):
    def __new__(mcs, *args, **kwargs):
        cls = super().__new__(mcs, *args, **kwargs)
        cls.some_method = classmethod(some_method)
        return cls


class MyABC(ABC):
    @classmethod
    def some_method(cls, x: str) -> str:
        return x


class MyClassWithSomeMethod(metaclass=MyMeta):
    pass


def call_some_method(cls: Type[MyClassWithSomeMethod]) -> str:
    return cls.some_method("A")


if __name__ == "__main__":
    mc = MyClassWithSomeMethod()
    assert isinstance(mc, MyClassWithSomeMethod)
    assert call_some_method(MyClassWithSomeMethod) == "result A"
Run Code Online (Sandbox Code Playgroud)

然而,MyPy对此很不满意:

minimal_example.py:27: error: …
Run Code Online (Sandbox Code Playgroud)

python metaclass type-hinting mypy python-typing

4
推荐指数
1
解决办法
2185
查看次数

Mypy - 为什么 TypeVar 在没有指定界限的情况下不起作用

我试图理解类型注释,我有以下代码:

from typing import TypeVar

T = TypeVar('T')

class MyClass():
    x: int = 10

def foo(obj: T) -> None:
    print(obj.x)

foo(MyClass())
Run Code Online (Sandbox Code Playgroud)

当我运行 mypy 时,出现以下错误:

main.py:9: error: "T" has no attribute "x"
Found 1 error in 1 file (checked 1 source file)
Run Code Online (Sandbox Code Playgroud)

但是当我添加bound='MyClass'到时TypeVar,它没有显示任何错误。

这种行为的原因是什么?我尝试阅读文档,但没有找到任何关于bound设置为默认值时到底发生了什么的答案。

python mypy

3
推荐指数
1
解决办法
3751
查看次数

使用 types.Literal 的正确方法是什么?

我的代码看起来像这样,BDW 运行良好,没有任何错误

from typing import Literal

def verify(word: str) -> Literal['Hello XY']:
    a = 'Hello ' + word
    return a

a = verify('XY')
Run Code Online (Sandbox Code Playgroud)

虽然,当我尝试使用 mypy 进行类型检查时,它会抛出错误error: Incompatible return value type (got "str", expected "Literal['Hello XY']")

注意:要执行类型检查mypy ./filename.py,只需在 pip 安装 mypy 后执行 。

另外,当我这样做时,类型检查工作正常

from typing import Literal

def verify(word: str) -> Literal['Hello XY']:
    a = 'Hello ' + word
    return 'Hello XY' #changed here

a = verify('XY')
Run Code Online (Sandbox Code Playgroud)

我缺少什么?

python typechecking type-hinting mypy python-typing

3
推荐指数
1
解决办法
6729
查看次数