Python 如何键入一个类型为封闭类的方法?
我在python 3中有以下代码:Python 如何键入一个类型为封闭类的方法?,python,python-3.x,pycharm,typing,python-3.5,Python,Python 3.x,Pycharm,Typing,Python 3.5,我在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)说,无法
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)说,无法解析参考位置(在\uuuuuuuuuuuuuuuu添加
方法中)。我应该如何指定我期望返回类型为Position
编辑:我认为这实际上是一个问题。它实际上在警告和代码完成中使用了这些信息
但是如果我错了,请纠正我,并且需要使用其他语法。在解析类主体本身时,名称“Position”不可用。我不知道您是如何使用类型声明的,但是Python的PEP 484——如果使用这些类型提示,大多数模式都应该使用PEP 484,它表示您可以在此时将名称作为字符串:
def __add__(self, other: 'Position') -> 'Position':
return Position(self.x + other.x, self.y + other.y)
检查-符合的工具将知道从那里打开类名并使用它。(请务必记住,Python语言本身不做这些注释——它们通常用于静态代码分析,或者可以有一个用于运行时类型检查的库/框架——但必须显式设置)
更新同样,从Python 3.7开始,检查-从Python 3.8开始,可以从uuu future uuu导入注释编写
,以推迟注释的评估-前向引用类应该可以直接工作。在解析类主体本身时,名称“Position”不可用。我不知道您是如何使用类型声明的,但是Python的PEP 484—如果使用这些类型提示,大多数模式都应该使用PEP 484—表示此时可以将名称作为字符串:
def __add__(self, other: 'Position') -> 'Position':
return Position(self.x + other.x, self.y + other.y)
检查-符合的工具将知道从那里打开类名并使用它。(请务必记住,Python语言本身不做这些注释——它们通常用于静态代码分析,或者可以有一个用于运行时类型检查的库/框架——但必须显式设置)
更新同样,从Python 3.7开始,检查-从Python 3.8开始,可以从uuu future uuu导入注释编写,以推迟注释的评估-前向引用类应该可以直接工作。TL;DR:如果您使用的是Python 3.10或更高版本,它就可以工作了。从今天(2019年)开始,在3.7+中,必须使用future语句(from uuuu future\uuuuu import annotations
)打开此功能。在Python 3.6或更低版本中,使用字符串
我猜你得到了这个例外:
NameError: name 'Position' is not defined
这是因为必须先定义Position
,然后才能在注释中使用它,除非您使用的是Python 3.10或更高版本
Python 3.7+:来自未来导入注释
Python 3.7引入了一个模块,该模块使用来自uuu future\uuuuu导入注释的future语句,将注释自动存储为字符串:
from __future__ import annotations
class Position:
def __add__(self, other: Position) -> Position:
...
这将成为Python3.10中的默认设置。由于Python仍然是一种动态类型化语言,因此在运行时不会进行类型检查,因此类型注释应该不会对性能产生影响,对吗?错!在Python3.7之前,如果您导入类型,您将看到在升级到3.7时,类型模块通常是如此。
PythonTL;DR:如果您使用的是Python 3.10或更高版本,它就可以正常工作。从今天(2019年)起,在3.7+中,您必须使用future语句(from uuuuu future\uuuuuuu导入注释
)打开此功能。在Python 3.6或更低版本中,使用字符串
我猜你得到了这个例外:
NameError: name 'Position' is not defined
这是因为必须先定义Position
,然后才能在注释中使用它,除非您使用的是Python 3.10或更高版本
Python 3.7+:来自未来导入注释
Python 3.7引入了一个模块,该模块使用来自uuu future\uuuuu导入注释的future语句,将注释自动存储为字符串:
from __future__ import annotations
class Position:
def __add__(self, other: Position) -> Position:
...
这将成为Python3.10中的默认设置。由于Python仍然是一种动态类型化语言,因此在运行时不会进行类型检查,因此类型注释应该不会对性能产生影响,对吗?错!在Python3.7之前,如果您导入类型,您将看到在升级到3.7时,类型模块通常是如此。
Python将类型指定为string很好,但是我们基本上绕过了解析器,这让我有点恼火。因此,您最好不要拼错这些文本字符串中的任何一个:
def __add__(self, other: 'Position') -> 'Position':
return Position(self.x + other.x, self.y + other.y)
一个微小的变化是使用绑定的typevar,至少在声明typevar时只需编写一次字符串:
from typing import TypeVar
T = TypeVar('T', bound='Position')
class Position:
def __init__(self, x: int, y: int):
self.x = x
self.y = y
def __add__(self, other: T) -> T:
return Position(self.x + other.x, self.y + other.y)
将类型指定为string很好,但总让我有点恼火,因为我们基本上绕过了解析器。因此,您最好不要拼错这些文本字符串中的任何一个:
def __add__(self, other: 'Position') -> 'Position':
return Position(self.x + other.x, self.y + other.y)
一个微小的变化是使用绑定的typevar,至少在声明typevar时只需编写一次字符串:
from typing import TypeVar
T = TypeVar('T', bound='Position')
class Position:
def __init__(self, x: int, y: int):
self.x = x
self.y = y
def __add__(self, other: T) -> T:
return Position(self.x + other.x, self.y + other.y)
如果可以接受基于字符串的类型提示,则也可以使用\uuuu qualname\uuuu
项。它包含类的名称,并且在类定义的主体中可用
class MyClass:
@classmethod
def make_new(cls) -> __qualname__:
return cls()
通过这样做,重命名类并不意味着修改类型提示。但我个人不希望智能代码编辑器能够很好地处理此表单。当基于字符串的类型提示可以接受时,也可以使用\uuuuuqalname\uuuqu
项。它包含类的名称,并且可以在类定义的主体中使用。
class MyClass:
@classmethod
def make_new(cls) -> __qualname__:
return cls()
通过这样做,重命名类并不意味着修改类型提示。但我个人不希望智能代码编辑器能够很好地处理此表单。如果您只关心修复名称错误:未定义名称“位置”
,您可以将类名指定为字符串:
def __add__(self, other: 'Position') -> 'Position':
或者,如果您使用Python3.7或更高版本,请将以下行添加到
def __add__(self, other: 'Position') -> 'Position':
return Position(self.x + other.x, self.y + other.y)
from typing import TypeVar
T = TypeVar('T', bound='Position')
class Position:
def __init__(self, x: int, y: int):
self.x = x
self.y = y
def __add__(self, other: T) -> T:
return Position(self.x + other.x, self.y + other.y)
class MyClass:
@classmethod
def make_new(cls) -> __qualname__:
return cls()
def __add__(self, other: 'Position') -> 'Position':
from __future__ import annotations
from __future__ import annotations
from typing import TypeVar
T = TypeVar('T', bound=Position)
class Position:
def __init__(self, x: int, y: int):
self.x = x
self.y = y
def __add__(self: T, other: Position) -> T:
return type(self)(self.x + other.x, self.y + other.y)
def copy(self: T) -> T:
return type(self)(self.x, self.y)
class DynamicParent:
def func(self):
# roundabout way of returning self in order to have inherited type hints of the return
# https://stackoverflow.com/a/64938978
_self:self.__class__ = self
return _self
class StaticParent:
def func(self) -> 'StaticParent':
return self
class StaticChild(StaticParent):
pass
class DynamicChild(DynamicParent):
pass
static_child = StaticChild()
dynamic_child = DynamicChild()