标签: mypy

Python 类型:从返回 Union 的函数缩小类型范围

我很难找到满足的返回类型mypy。我有两个功能。第一个返回一个Union类型,因为该类型取决于赋予函数的参数。第二个函数使用默认参数调用第一个函数。因此,该类型不是一种Union类型——它可以缩小到Union.

让我给你举一个我的问题的一个非常简单的例子:

from typing import Union


def first(as_string: bool) -> Union[str, int]:
    if as_string:
        return "42"
    else:
        return 42


def second(as_string: bool) -> str:
    return first(True)
Run Code Online (Sandbox Code Playgroud)

这会导致错误:

Incompatible return value type (got "str", expected "Union[str, int]")
Run Code Online (Sandbox Code Playgroud)

如何mypy在仍然使用类型提示的同时防止抛出错误?

如果您想建议拆分第一个函数,请记住这只是一个简化。我的(第一个)函数接收一个函数(sklearn.metricsfunction)并且大多数时候会返回一个标量。仅当应用混淆矩阵时,类型才会发生变化。第一个函数进行一些预处理,然后应用度量。我只是想为混淆矩阵提供一个不同名称的函数,因为我认为它是度量的特殊情况。

python typing mypy

17
推荐指数
1
解决办法
5890
查看次数

使用 mypy / PEP-526 定义一个 jsonable 类型

可以通过 json.dumps 转换为 JSON 字符串的值有: - 标量:数字和字符串 - 容器:映射和可迭代

Union[str, int, float, Mapping, Iterable]

你有更好的建议吗?

mypy

16
推荐指数
3
解决办法
7984
查看次数

变量“foo_class”作为类型无效,但为什么呢?

我有类似的东西:

from typing import Type


class Foo:
    pass


def make_a_foobar_class(foo_class: Type[Foo]) -> Type[Foo]:

    class FooBar(foo_class):
        # this.py:10: error: Variable "foo_class" is not valid as a type
        # this.py:10: error: Invalid base class "foo_class"
        pass

    return FooBar


print(make_a_foobar_class(Foo)())
Run Code Online (Sandbox Code Playgroud)

运行会mypy在该行抛出这两个错误(作为注释添加 ^)class FooBar(foo_class):

该代码似乎工作得很好:

$ python this.py
<__main__.make_a_foobar_class.<locals>.FooBar object at 0x10a422be0>
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

python-3.x mypy python-typing

16
推荐指数
1
解决办法
6026
查看次数

Python:将变量注释为 TypedDict 的键

基本上是这个问题(尚未得到解答)的精炼版本。

我想声明的是,变量应该只采用TypedDict.

目前我正在定义一个单独的Literal类型来表示键,例如:

from typing import Literal, TypedDict


class MyTD(TypedDict):
    a: int
    b: int


mytd = MyTD(a=1, b=2)

key = "a"

mytd[key]  # error: TypedDict key must be a string literal; expected one of ('a', 'b')

MyTDKeyT = Literal["a", "b"]

typed_key: MyTDKeyT = "b"

mytd[typed_key]  # no error
Run Code Online (Sandbox Code Playgroud)

我希望能够Literal出于想要最小化重复代码的所有常见原因替换定义。

伪代码:

key: Keys[MyTD] = "a"
mytd[key]  # would be no error
not_key: Keys[MyTD] = "z"  # error
Run Code Online (Sandbox Code Playgroud)

有办法实现这一点吗?

为了澄清,鉴于 mypy 可以告诉我键类型需要是“a”或“b”的文字,我希望可能有一种不太容易出错的方法来将变量注释为该类型,而不是使用并排维护两个单独的键列表,一次在定义中TypedDict,一次在Literal …

python mypy python-typing

16
推荐指数
1
解决办法
2942
查看次数

如何让抽象数据类传递给mypy?

mypy v0.910 拒绝 Python 3.9 中的抽象数据类。这是最小的可重复示例:

from abc import ABC, abstractmethod
from dataclasses import dataclass

@dataclass
class Liquid(ABC):

    @abstractmethod
    def drip(self) -> None:
        pass
Run Code Online (Sandbox Code Playgroud)

这是错误消息:

$ mypy --python-version 3.9 so.py
so.py:4: error: Only concrete class can be given where "Type[Liquid]" is expected
Found 1 error in 1 file (checked 1 source file)
Run Code Online (Sandbox Code Playgroud)

如何让此代码通过mypy


笔记

我从mypy 问题 #5374中了解到,这是mypy中的一个错误,于 2018 年首次注意到,但仍未得到纠正。不过,我认为人们必须将mypy与抽象数据类一起使用,因此必须有一种解决方法或正确的方法来定义或注释该类。有什么推荐的?

错误消息的基础似乎是mypy假设任何类型的对象都Type可以实例化,但抽象类不能实例化。这似乎是错误,因为Type定义为表示类对象,而不一定是具体的类对象(即可以实例化的类对象)。

添加# type: ignore到包含的行 …

python abstract-base-class mypy python-dataclasses python-typing

16
推荐指数
2
解决办法
5552
查看次数

使用Python输入模块指定Sequence或List的长度

我正在给Python typing模块一个镜头.

我知道指定List以下*的长度是有效的:

List[float, float, float]   # List of 3 floats <-- NOTE: this is not valid Python
Run Code Online (Sandbox Code Playgroud)

是否有更长的名单的简写?如果我想将它设置为10个花车怎么办?

List[float * 10]   # This doesn't work.
Run Code Online (Sandbox Code Playgroud)

如果这是可能的,任何想法,这将是方便的.


*注意:事实证明Sequence[]以这种方式向(及其子类)提供多个参数当前不是有效的Python.此外,目前不可能以这种方式Sequence使用typing模块指定长度.

python type-hinting python-3.x mypy

15
推荐指数
4
解决办法
4423
查看次数

错误:跳过分析“flask_mysqldb”:找到模块但没有类型提示或库存根

我正在使用 Python 3.6 和flask. 我曾经flask-mysqldb连接到MySQL,但是每当我尝试mypy在我的程序上运行时,我都会收到此错误:

跳过分析“flask_mysqldb”:找到模块但没有类型提示或库存根。

我尝试mypy使用标志ignore-missing-importsfollow-imports=skip. 然后我没有收到错误。为什么我会收到这个错误?如何在不添加任何其他标志的情况下解决此问题?

python mypy flask-mysql

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

是否有使包符合 PEP-561 的最佳实践?

我正在编写一个 Python 项目,该项目作为包发布到类似 pypi 的存储库(使用setuptoolstwine)。我在我的代码中使用类型提示。

问题是,从不同的项目导入包并运行时mypy,出现以下错误: error: Skipping analyzing 'XXX': found module but no type hints or library stubs

据我了解,我收到此错误是因为我的包不符合https://www.python.org/dev/peps/pep-0561/

在网上搜索了一些之后,我没有找到一种非手动将所需文件添加到包中的方法。

我求助于编写自己的代码:

  1. 运行stubgen以创建存根文件。
  2. py.typed在每个目录中创建文件。
  3. 在文件的dictinpackage_data字段中收集所有创建的setup.py文件。

这段代码解决了这个问题并且mypy运行没有错误。但这对我来说感觉非常错误。是否有标准工具可以使包符合 PEP-561?我还缺少其他东西吗?

python setuptools mypy

15
推荐指数
2
解决办法
2720
查看次数

functools.partial 的正确类型提示

正确的类型提示是什么functools.partial?我有一个返回 a 的函数partial,我想输入提示,这样就mypy不会抛出任何错误:

def my_func() -> ?:
    return partial(foo, bar="baz")
Run Code Online (Sandbox Code Playgroud)

比更具体typing.Callable

python functools mypy

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

如何使用 AsyncGenerator 和 AsyncContextManager 正确指定类型提示

考虑下面的代码

import contextlib
import abc
import asyncio

from typing import AsyncContextManager, AsyncGenerator, AsyncIterator


class Base:

    @abc.abstractmethod
    async def subscribe(self) -> AsyncContextManager[AsyncGenerator[int, None]]:
        pass

class Impl1(Base):

    @contextlib.asynccontextmanager
    async def subscribe(self) ->  AsyncIterator[ AsyncGenerator[int, None] ]: <-- mypy error here

        async def _generator():
            for i in range(5):
                await asyncio.sleep(1)
                yield i
                    
        yield _generator()
Run Code Online (Sandbox Code Playgroud)

对于Impl1.subscribemypy 给出错误

Signature of "subscribe" incompatible with supertype "Base"
Run Code Online (Sandbox Code Playgroud)

在上述情况下指定类型提示的正确方法是什么?或者 mypy 这里错了?

python type-hinting mypy

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