社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
私信  •  关注

Michael0x2a

Michael0x2a 最近创建的主题
Michael0x2a 最近回复了
5 年前
回复了 Michael0x2a 创建的主题 » Python将属性保留为未赋值,并使用省略号或None+float类型提示

对于简单的情况,实际上可以不用在构造函数中执行任何操作:如果执行以下操作,mypy和Pycharm将继续正确推断字段的类型:

class SomeClass:
    def called_during_runtime(self) -> None:
        self._unassigned_val = 1.0

如果您的函数以足够复杂的方式为该字段赋值,则类型检查器可能会阻塞,不知道该做什么。在这种情况下,您可以使用 Variable annotations 如果您使用的是Python3.6或更高版本:

class SomeClass:
    _unassigned_val: float

    def called_during_runtime(self) -> None:
        self._unassigned_val = 1.0

这完全等同于运行时的第一种方法。

如果需要支持较旧版本的Python,则可以使用另一种技术创建一个“假”sentinel值,该值被赋予一种 Any ,全动态类型:

from typing import Any

BOGUS = object()  # type: Any

class SomeClass:
    def __init__(self) -> None:
        self._unassigned_val = BOGUS  # type: float

    def called_during_runtime(self) -> None:
        self._unassigned_val = 1.0

如果您改变主意并决定偏向类型检查器,请更积极地处理其警告,您可以始终声明您的值可以是 任何一个 浮动或无:

from typing import Optional

class SomeClass:
    def __init__(self) -> None:
        self._unassigned_val = None  # type: Optional[float]

    def called_during_runtime(self) -> None:
        self._unassigned_val = 1.0

    def get_with_default(self, default: float) -> float:
        if self._unassigned_val is None:
            return default
        else:
            return self._unassigned_val

注意,然后可以使用 self._unassigned_val is not None , self._unassigned_val is None ,或 isinstance(self._unassigned_val, float) 在if语句中检查,并断言让类型检查器有条件地缩小字段的类型。

最后一种方法是我个人所做的:我是类型检查程序的粉丝,并且设置我的工具来非常积极地检测潜在的问题。

关于省略号的最后一个注意事项:使用省略号作为占位符仅适用于存根,并且在处理诸如 Protocols abstract classes --基本上,如果您在运行时从未实际使用字段/方法参数/任何东西的值。

5 年前
回复了 Michael0x2a 创建的主题 » 使用异常处理的Python类型

Mypy并不真正深入地理解异常——在本例中,它不理解因为您正在捕获attributerror,所以它可以忽略“如果 regex.match(path) 没有吗?”案例。

一般来说,mypy的基本假设是 foo 带类型 Union[A, B] 你也知道 foo.bar() ,两种类型 A B 有一个 bar() 方法。

如果这些类型中只有一个有 巴() 方法,您需要执行以下操作之一:

  1. 在执行属性访问之前,给mypy足够的信息来将联合范围缩小到一个相关类型。例如,isinstance检查, x is not None 检查。。。
  2. 确认您正在尝试执行类型检查器无法理解的操作,并解决抑制生成的错误的问题。例如,可以强制转换类型,在 # type: ignore 评论,想办法 充满活力 Any 键入。。。
  3. 找到一种重新设计代码的方法来回避这个问题。

(在这个特殊的例子中,我想另一个选择可能是向mypy提交一个pull请求,添加对这个模式的支持。但我不确定这是否真的可行:改变任何一种基本假设在多个维度上都是困难的。)

类似地,Mypy也不理解深层次的正则表达式——例如,不尝试分析正则表达式来确定将得到多少组,因此不理解特定的正则表达式恰好将字符串与正好两个组匹配。它所能做的就是断言组将返回一些未知数目的字符串,因此 Sequence[str] 而不是 Tuple[str, str] .

这种限制通常在类型检查程序中很常见,实际上:主流语言中的大多数类型系统并不真正支持基于传入的任何实际值的内容对返回类型进行谓词。这种类型的系统(依赖型系统、求精型系统……)很难实现,而且对于最终用户来说,往往有一个陡峭的学习曲线。

然而,它 更容易让mypy在 尽力而为 通过写一个 mypy plugin ,如果你愿意的话。具体来说,试着看看 get_method_hook() get_function_hook() .

6 年前
回复了 Michael0x2a 创建的主题 » python 3.7嵌套数据类mypy类型检查错误

我不知道 nested_dataclass 它似乎不是数据类模块的标准部分的装饰器。

因此,当您尝试实例化c时,mypy将无法理解正在发生的任何特殊逻辑。

有两种可能的解决方案:

  1. 只是使用 @dataclass 放弃你正在使用的任何自定义逻辑。
  2. 为mypy编写一个可以理解 @nested_dataclass 装饰工。通过查看dataclasses插件 comes baked into mypy 是的。
6 年前
回复了 Michael0x2a 创建的主题 » python-typing-union的可订阅类型

创建类型别名 Union[List[T], Array[T]] 应该工作:

from typing import TypeVar, Union, List

T = TypeVar('T')
Array = Union[List[T], numpy.ndarray[T]]

def foo(bar: Array[int]) -> None: pass

查看mypy文档 generic type aliases 更多关于这项技术的信息。

此代码可能在运行时失败,因为 numpy.ndarray 实际上在运行时不可订阅,仅在类型提示世界中。您可以通过隐藏自定义类型提示来解决这一问题。 typing.TYPE_CHECKING Guard,在运行时始终为false,在类型检查时始终为true。

在Python 3.7 +中,您可以做到这一点:

from __future__ import annotations
from typing import TypeVar, Union, List, TYPE_CHECKING

if TYPE_CHECKING:
    T = TypeVar('T')
    Array = Union[List[T], numpy.ndarray[T]]

def foo(bar: Array[int]) -> None: pass

你得把你的 Array[int] 但是,在旧版本python 3的字符串中:

from typing import TypeVar, Union, List, TYPE_CHECKING

if TYPE_CHECKING:
    T = TypeVar('T')
    Array = Union[List[T], numpy.ndarray[T]]

def foo(bar: "Array[int]") -> None: pass

注意,尝试构建自己的 Array 在运行时将其他几个类型提示组合在一起的类型提示不太可能起作用:像mypy这样的静态分析工具实际上是通过在不运行代码的情况下对代码进行分析来工作的:它实际上不会尝试对自定义项中的任何内容进行求值 数组 班级。

一般来说,在运行时尝试“使用”类型提示往往充满风险:它们实际上只是用来作为类型提示的。

最后,你似乎误解了 NewType 是为了。我推荐阅读 the relevant docs for more info

6 年前
回复了 Michael0x2a 创建的主题 » 为python(mypy)声明外部类型

一天结束的时候,你需要以一种或另一种形式对Mypy撒谎——问题的归根结底就是这样做的符合人体工程学和方便的方式是什么。

这样做最方便的方法可能是在单独的文件中定义额外的文件,并将它们全局导入到脚本中。你可以利用 typing.TYPE_CHECKING variable——该变量在运行时始终为false,但在类型检查时被视为true。所以,你可能会这样做:

from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from my_ironpython_globals import *

不过,最好确保没有人在运行时尝试使用自定义模块中的任何内容。确保这一点的一种方法是在 stub file --存根文件是python的类似于typescript的定义文件。

简而言之,创建以 .pyi 扩展(而不是 .py )在你的项目中定义所有的东西。

如果您想查看存根文件的示例,请尝试签出 typeshed ,标准库和一些流行的第三方库的存根存储库。(Mypy收到一份打字稿)。他们 contribution guidelines 如果你对这类东西感兴趣的话,有一个风格指南。

如果要将新创建的存根作为第三方模块分发,只需pip安装和使用,请创建一个 PEP 561-compliant package 包含类型提示。


您可以采用的另一种方法是使用自己的自定义类型化版本。也就是说,克隆或分叉 排版 并修改 stdlib/*/builtins.pyi 文件,以便它们包含特定于Ironpython的全局变量。

然后,使用 --custom-typeshed-dir 标志:例如Do mypy --custom-typeshed-dir path/to/my/typeshed mycode

如果键入此标志序列变得单调乏味,请创建一个 configuration file 在那里编码你的设置。

这种方法比第一种方法更具原则性,因为你教mypy合法地识别任何可用的全局变量。但是,必须维护自己的typeshed叉+跟上上游的变化 很多工作(这种碎片化可能不理想)。

因此,如果您确实决定采用这种方法,那么首先应该讨论一下typeshed的问题跟踪程序。排版(以及PEP484生态系统)总体上还是相当新的,所以仍然有空间影响它的生长方向。