- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在 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__
方法中)。我应该如何指定我希望返回类型为 Position
类型?
编辑:我认为这实际上是一个 PyCharm 问题。它实际上在其警告和代码完成中使用了这些信息。
但如果我错了,请纠正我,并且需要使用一些其他语法。
最佳答案
TL;DR:截至今天(2019 年),在 Python 3.7+ 中,您可以使用“future”语句from __future__ import annotations
打开此功能。
(from __future__ import annotations
启用的行为可能成为 future Python 版本的默认行为,was going 将成为 Python 3.10 的默认行为。但是, 3.10 中的更改 was reverted 在最后一刻发生,现在可能根本不会发生。)
在 Python 3.6 或更低版本中,您应该使用字符串。
我猜你遇到了这个异常:
NameError: name 'Position' is not defined
这是因为 Position
必须先定义,然后才能在注释中使用它,除非您将 Python 与 PEP 563 一起使用启用更改。
from __future__ import annotations
Python 3.7 引入了 PEP 563: postponed evaluation of annotations .使用 future 语句 from __future__ import annotations
的模块将自动将注释存储为字符串:
from __future__ import annotations
class Position:
def __add__(self, other: Position) -> Position:
...
这已计划成为 Python 3.10 中的默认设置,但现在已推迟此更改。由于 Python 仍然是一种动态类型语言,因此在运行时不进行类型检查,类型注释应该不会对性能产生影响,对吧?错误的!在 Python 3.7 之前,打字模块曾经是 one of the slowest python modules in core所以对于涉及导入typing
模块的代码,您将看到一个up to 7 times increase in performance。当您升级到 3.7 时。
According to PEP 484 ,您应该使用字符串而不是类本身:
class Position:
...
def __add__(self, other: 'Position') -> 'Position':
...
如果您使用 Django 框架,这可能很熟悉,因为 Django 模型也使用字符串进行前向引用(外部模型是 self
或尚未声明的外键定义)。这应该适用于 Pycharm 和其他工具。
PEP 484 和 PEP 563 的相关部分,免去您的旅途:
Forward references
When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later.
A situation where this occurs commonly is the definition of a container class, where the class being defined occurs in the signature of some of the methods. For example, the following code (the start of a simple binary tree implementation) does not work:
class Tree:
def __init__(self, left: Tree, right: Tree):
self.left = left
self.right = rightTo address this, we write:
class Tree:
def __init__(self, left: 'Tree', right: 'Tree'):
self.left = left
self.right = rightThe string literal should contain a valid Python expression (i.e., compile(lit, '', 'eval') should be a valid code object) and it should evaluate without errors once the module has been fully loaded. The local and global namespace in which it is evaluated should be the same namespaces in which default arguments to the same function would be evaluated.
和 PEP 563:
Implementation
In Python 3.10, function and variable annotations will no longer be evaluated at definition time. Instead, a string form will be preserved in the respective
__annotations__
dictionary. Static type checkers will see no difference in behavior, whereas tools using annotations at runtime will have to perform postponed evaluation....
Enabling the future behavior in Python 3.7
The functionality described above can be enabled starting from Python 3.7 using the following special import:
from __future__ import annotations
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
您可能想尝试一些 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
可能太麻烦了。
关于python - 如何键入具有封闭类类型的提示方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37377649/
从the documentation, 13.5.5: When the last parameter of a method is a closure, you can place the clos
Bjarne Stroustrup 写道: “友元类必须事先在封闭范围内声明或在非类范围内定义,立即封闭声明它为友元的类” 语句的第一部分不是多余的,因为“立即包含类的非类范围”包括“先前在封闭范围中
我有一个网格(如下例),其中包含外墙(标记为 W)、环境 block (E)、开放空间 (o) 和事件点 (A)。目前,此网格存储在 [,] 中,其中包含与给定点关联的所有数据。我试图确定是否包含一个
我正在尝试使用 this blogpost's approach to higher-kinded data without dangling Identity functors for the tr
在下面的代码中: package main import ( "fmt" "time" ) func asChan(vs ...int) <-chan int { c := m
我在传递和评估闭包列表时遇到困难。经过大量简化,该程序显示出与我正在尝试编写的程序相同的错误: use std::vec::flat_map; #[main] fn main() { let li
我正在努力成为一名好公民,并尽可能远离全局范围。有没有办法访问不在全局范围内的 setTimeout 变量? 因此,在此示例中,某人将如何取消“计时器”? myObject.timedAction =
考虑这个例子: def A(): b = 1 def B(): # I can access 'b' from here. print(b)
val listPlans: List = newPlans.mapTry { it.data.map { Plan(it.id, it.nam
我目前正在尝试使用SinonJS对我的 angular.service 进行单元测试,但是遇到了一个问题,希望有人可以阐明为什么会发生这种情况。我已经重构了当前的项目以说明当前的问题。 我还提供了DE
我正在使用 Go channel ,我想知道关闭 channel 和将其设置为 nil 之间有什么区别? 编辑: 在此example ,我想通过关闭 channel 或设置为零来断开发送者和接收者的连
我的应用程序有一个奇怪的行为,我不知道它来自哪里。我已经为 TextView 内容实现了 NSScanner,效果非常好。扫描器与文本存储结合使用,通过 TextView 委托(delegate)方法
我不知道如何让 MyBatis 生成封闭的 or 语句: WHERE x.token = ? AND ( (x.scene = 'A' OR x.scene = 'B')) 这是一个令人惊讶的简单
我不希望这是一个摄像头检测程序。这是一个程序,可以检测应用程序屏幕上颜色的传递。 我想要做的是检测大于 5x5 像素的黑色何时穿过屏幕上定义的空间区域。我想过用一个大区域来拉伸(stretch)整个宽
我一直在使用 RDFLib 来解析数据并将其插入到三元组中。我遇到的一个常见问题是,从关联数据存储库解析时,没有尖括号括起 URL。 要上传数据,我必须手动添加 并使用 URIRef重新创建 URL。
我已经阅读了很多有关此问题的帖子,但我仍然不确定我是否完全理解这些定义。 以下是我认为不同术语的示例。我是否走在正确的轨道上,或者我仍然不理解这些概念。谢谢 Array - unbound and o
我为我的 Android 应用设置了 GooglePlay 内部和封闭式 Alpha 测试设置。 它非常适合允许测试人员加入计划并安装应用程序,但是当我从测试人员电子邮件列表中删除测试人员时,他们仍然
我是一名优秀的程序员,十分优秀!