如何使用封闭类的类型键入提示方法?

2023-12-22

我在 Python 3 中有以下代码:

class Position:

    def __init__(self, x: int, y: int):
        self.x = x
        self.y = y

    def __add__(self, other: Position) -> Position:
        return Position(self.x + other.x, self.y + other.y)

但我的编辑(PyCharm)说参考文献Position无法解决(在__add__方法)。我应该如何指定我期望返回类型为 typePosition?

编辑:我认为这实际上是一个 PyCharm 问题。它实际上在警告和代码完成中使用了这些信息。

但如果我错了并且需要使用其他语法,请纠正我。


TL;DR:从今天(2019 年)开始,在 Python 3.7+ 中,您可以使用“future”语句打开此功能,from __future__ import annotations.

(该行为由from __future__ import annotations might成为 Python 未来版本中的默认值,并且当时正在 https://www.python.org/dev/peps/pep-0563/在 Python 3.10 中设为默认值。然而3.10的改变已恢复 https://mail.python.org/archives/list/python-dev@python.org/thread/CLVXXPQ2T2LQ5MP2Y53VVQFCXYWQJHKZ/在最后一刻,现在可能根本不会发生。 Python 3.11不包括它 https://docs.python.org/3/whatsnew/3.11.html#pep-563-may-not-be-the-future)

在 Python 3.6 或更低版本中,您应该使用字符串。


我猜你遇到了这个例外:

NameError: name 'Position' is not defined

这是因为Position必须先定义,然后才能在注释中使用它,除非您将 Python 与PEP 563 https://www.python.org/dev/peps/pep-0563/启用更改。

Python 3.7+:from __future__ import annotations

Python 3.7 引入PEP 563:推迟注释评估 https://www.python.org/dev/peps/pep-0563/。使用 future 语句的模块from __future__ import annotations将自动将注释存储为字符串:

from __future__ import annotations

class Position:
    def __add__(self, other: Position) -> Position:
        ...

这原计划成为 Python 3.10 中的默认设置,但这一更改现已推迟。由于 Python 仍然是一种动态类型语言,因此在运行时不会进行类型检查,因此类型注释应该不会影响性能,对吧?错误的!在 Python 3.7 之前,输入模块曾经是核心中最慢的 python 模块之一 https://www.python.org/dev/peps/pep-0560/#performance so 对于涉及导入的代码typing模块,您将看到一个性能提升高达 7 倍 https://docs.python.org/3.7/whatsnew/3.7.html#pep-560-core-support-for-typing-module-and-generic-types当你升级到3.7时。

Python

根据 PEP 484 https://www.python.org/dev/peps/pep-0484/#forward-references,您应该使用字符串而不是类本身:

class Position:
    ...
    def __add__(self, other: 'Position') -> 'Position':
       ...

如果您使用 Django 框架,这可能很熟悉,因为 Django 模型也使用字符串进行前向引用(外键定义,其中外部模型是self或尚未宣布)。这应该与 Pycharm 和其他工具一起使用。

Sources

PEP 484 和 PEP 563 的相关部分,免去您的旅途:

转发参考文献 https://www.python.org/dev/peps/pep-0484/#forward-references

当类型提示包含尚未定义的名称时,该定义可能会表示为字符串文字,以便稍后解析。

这种情况经常发生的情况是容器类的定义,其中所定义的类出现在某些方法的签名中。例如,以下代码(简单二叉树实现的开始)不起作用:

class Tree:
    def __init__(self, left: Tree, right: Tree):
        self.left = left
        self.right = right

为了解决这个问题,我们写道:

class Tree:
    def __init__(self, left: 'Tree', right: 'Tree'):
        self.left = left
        self.right = right

字符串文字应包含有效的 Python 表达式(即,compile(lit, '', 'eval') 应该是有效的代码对象),并且一旦模块完全加载,它的计算结果应该不会出现错误。计算它的本地和全局命名空间应该与计算同一函数的默认参数的命名空间相同。

和 PEP 563:

执行 https://www.python.org/dev/peps/pep-0563/#implementation

在 Python 3.10 中,函数和变量注释将不再在定义时评估。相反,字符串形式将保留在各自的__annotations__字典。静态类型检查器在行为上不会发现任何差异,而在运行时使用注释的工具将必须执行推迟的评估。

...

启用 Python 3.7 中的未来行为 https://www.python.org/dev/peps/pep-0563/#enabling-the-future-behavior-in-python-3-7

从 Python 3.7 开始,可以使用以下特殊导入启用上述功能:

from __future__ import annotations

您可能想做的事情

A. 定义一个虚拟对象Position

在类定义之前,放置一个虚拟定义:

class Position(object):
    pass


class Position(object):
    ...

这将摆脱NameError甚至看起来还不错:

>>> Position.__add__.__annotations__
{'other': __main__.Position, 'return': __main__.Position}

但真的是这样吗?

>>> for k, v in Position.__add__.__annotations__.items():
...     print(k, 'is Position:', v is Position)                                                                                                                                                                                                                  
return is Position: False
other is Position: False

B. Monkey-patch 以添加注释:

您可能想尝试一些 Python 元编程魔法并编写一个装饰器 对类定义进行猴子修补以添加注释:

class Position:
    ...
    def __add__(self, other):
        return self.__class__(self.x + other.x, self.y + other.y)

装饰者应该负责相当于这样的事情:

Position.__add__.__annotations__['return'] = Position
Position.__add__.__annotations__['other'] = Position

至少看起来是对的:

>>> for k, v in Position.__add__.__annotations__.items():
...     print(k, 'is Position:', v is Position)                                                                                                                                                                                                                  
return is Position: True
other is Position: True

大概是太麻烦了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用封闭类的类型键入提示方法? 的相关文章

  • 使用 openCV 对图像中的子图像进行通用检测

    免责声明 我是计算机视觉菜鸟 我看过很多关于如何在较大图像中查找特定子图像的堆栈溢出帖子 我的用例有点不同 因为我不希望它是具体的 而且我不确定如何做到这一点 如果可能的话 但我感觉应该如此 我有大量图像数据集 有时 其中一些图像是数据集的
  • Pycharm Python 控制台不打印输出

    我有一个从 Pycharm python 控制台调用的函数 但没有显示输出 In 2 def problem1 6 for i in range 1 101 2 print i end In 3 problem1 6 In 4 另一方面 像
  • 如何收集列表、字典等中重复计算的结果(或制作修改每个元素的列表的副本)?

    There are a great many existing Q A on Stack Overflow on this general theme but they are all either poor quality typical
  • 如何打印没有类型的defaultdict变量?

    在下面的代码中 from collections import defaultdict confusion proba dict defaultdict float for i in xrange 10 confusion proba di
  • 如何在Windows上模拟socket.socketpair

    标准Python函数套接字 套接字对 https docs python org 3 library socket html socket socketpair不幸的是 它在 Windows 上不可用 从 Python 3 4 1 开始 我
  • 将 github 上的包安装到 Spyder 中

    我一直在尝试安装并导入mpl finance来自 github 的包 在我的 Spyder 环境中没有成功 我努力了 pip install e git https github com matplotlib mpl finance git
  • __del__ 真的是析构函数吗?

    我主要用 C 做事情 其中 析构函数方法实际上是为了销毁所获取的资源 最近我开始使用python 这真的很有趣而且很棒 我开始了解到它有像java一样的GC 因此 没有过分强调对象所有权 构造和销毁 据我所知 init 方法对我来说在 py
  • 安装后 Anaconda 提示损坏

    我刚刚安装张量流GPU创建单独的后环境按照以下指示here https github com antoniosehk keras tensorflow windows installation 但是 安装后当我关闭提示窗口并打开新航站楼弹出
  • python 集合可以包含的值的数量是否有限制?

    我正在尝试使用 python 设置作为 mysql 表中 ids 的过滤器 python集存储了所有要过滤的id 现在大约有30000个 这个数字会随着时间的推移慢慢增长 我担心python集的最大容量 它可以包含的元素数量有限制吗 您最大
  • Pandas Dataframe 中 bool 值的条件前向填充

    问题 如何转发 fill boolTruepandas 数据框中的值 如果是当天的第一个条目 True 到一天结束时 请参阅以下示例和所需的输出 Data import pandas as pd import numpy as np df
  • Python:尝试检查有效的电话号码

    我正在尝试编写一个接受以下格式的电话号码的程序XXX XXX XXXX并将条目中的任何字母翻译为其相应的数字 现在我有了这个 如果启动不正确 它将允许您重新输入正确的数字 然后它会翻译输入的原始数字 我该如何解决 def main phon
  • 通过数据框与函数进行交互

    如果我有这样的日期框架 氮 EG 00 04 NEG 04 08 NEG 08 12 NEG 12 16 NEG 16 20 NEG 20 24 datum von 2017 10 12 21 69 15 36 0 87 1 42 0 76
  • 在Python中重置生成器对象

    我有一个由多个yield 返回的生成器对象 准备调用该生成器是相当耗时的操作 这就是为什么我想多次重复使用生成器 y FunctionWithYield for x in y print x here must be something t
  • 类型错误:只能使用标量值执行操作

    如果您能让我知道如何为所提供的表格绘制一些信息丰富的图表 我将不胜感激here https www iasplus com en resources ifrs topics use of ifrs 例如 我需要一个名为 国内非上市公司 非上
  • Python:计算字典的重复值

    我有一本字典如下 dictA unit1 test1 alpha unit1 test2 beta unit2 test1 alpha unit2 test2 gamma unit3 test1 delta unit3 test2 gamm
  • 设置 torch.gather(...) 调用的结果

    我有一个形状为 n x m 的 2D pytorch 张量 我想使用索引列表来索引第二个维度 可以使用 torch gather 完成 然后然后还设置新值到索引的结果 Example data torch tensor 0 1 2 3 4
  • 检查所有值是否作为字典中的键存在

    我有一个值列表和一本字典 我想确保列表中的每个值都作为字典中的键存在 目前我正在使用两组来确定字典中是否存在任何值 unmapped set foo set bar keys 有没有更Pythonic的方法来测试这个 感觉有点像黑客 您的方
  • 如何使用google colab在jupyter笔记本中显示GIF?

    我正在使用 google colab 想嵌入一个 gif 有谁知道如何做到这一点 我正在使用下面的代码 它并没有在笔记本中为 gif 制作动画 我希望笔记本是交互式的 这样人们就可以看到代码的动画效果 而无需运行它 我发现很多方法在 Goo
  • 使用基于正则表达式的部分匹配来选择 Pandas 数据帧的子数据帧

    我有一个 Pandas 数据框 它有两列 一列 进程参数 列 包含字符串 另一列 值 列 包含相应的浮点值 我需要过滤出部分匹配列 过程参数 中的一组键的子数据帧 并提取与这些键匹配的数据帧的两列 df pd DataFrame Proce
  • 您可以在 Python 类型注释中指定方差吗?

    你能发现下面代码中的错误吗 米皮不能 from typing import Dict Any def add items d Dict str Any gt None d foo 5 d Dict str str add items d f

随机推荐