使用PEP 484,有没有办法注释 classmethod 返回该类的实例?
例如
@dataclass
class Bar:
foo: str
@classmethod
def new_from_foo(cls, foo) -> Bar
...
Run Code Online (Sandbox Code Playgroud)
或者
@classmethod
def new_from_foo(cls, foo) -> cls
Run Code Online (Sandbox Code Playgroud) 函数注释:PEP-3107
背景:我是 Linux 上使用 CPython 3.4x 的 PyCharm 用户。我发现注释函数参数和返回类型很有帮助。当我使用这些方法时,IDE 可以更好地提示。
问题:对于自链方法,如何注释方法返回值?如果我使用类名,Python 会在编译时抛出异常:NameError: name 'X' is not defined
示例代码:
class X:
def yaya(self, x: int):
# Do stuff here
pass
def chained_yaya(self, x: int) -> X:
# Do stuff here
return self
Run Code Online (Sandbox Code Playgroud)
作为一个技巧,如果我把X = None它放在类声明之前,它就可以工作。但是,我不知道这种技术是否有不可预见的负面影响。
我想使Foo成为一个不变的对象。当我“扩展” foo时,我想获得一个Foo的新实例。我希望输入如下提示:
class Foo(object):
def extend(self, item:str) -> Foo:
pass
Run Code Online (Sandbox Code Playgroud)
看起来不错,但是IntelliJ并不同意。我在第二行的Foo下面得到一个红色的下划线。错误消息是:未解析的引用'Foo'。
我有点明白了这是什么意思:在tyme上,我们正在解析第2行,但是我们还没有对象Foo,因此解释器不知道Foo是什么意思。
但奇怪的是,对于PyCharm(但无效的python),这个非常不令人满意的替代方法就足够了:
class Foo(object):
def extend(self, item:str) -> Foo_:
pass
Foo_ = Foo
Run Code Online (Sandbox Code Playgroud)
那么有没有有效的方法来做到这一点?我如何在类型提示注释中说特定方法返回新的self实例。类?
我在带有PyCharm插件的IntelliJ的最新版本上使用Python 3.5。
我喜欢用于__qualname__工厂式类方法的返回类型注释,因为它不会对类名进行硬编码,因此可以保持子类的工作(参见此答案)。
class Foo:
@classmethod
def make(cls) -> __qualname__:
return cls()
Run Code Online (Sandbox Code Playgroud)
目前这似乎工作正常,但我不确定通过推迟注释评估(PEP 563)这是否仍然可能:PEP说
注释只能使用模块范围中存在的名称,因为使用本地名称的延迟评估不可靠(唯一的例外是由 解析的类级别名称
typing.get_type_hints())。
政治公众人物还表示:
该函数会自动解析函数和类
get_type_hints()的正确值。globalns它还自动提供正确localns的课程。
然而,下面的代码
from __future__ import annotations
import typing
class Foo():
@classmethod
def make(cls) -> __qualname__:
return cls()
print(typing.get_type_hints(Foo.make))
Run Code Online (Sandbox Code Playgroud)
失败了
File "qualname_test.py", line 11, in <module>
print(typing.get_type_hints(Foo.make))
File "/var/local/conda/envs/py37/lib/python3.7/typing.py", line 1004, in get_type_hints
value = _eval_type(value, globalns, localns)
File "/var/local/conda/envs/py37/lib/python3.7/typing.py", line 263, in _eval_type
return t._evaluate(globalns, localns)
File "/var/local/conda/envs/py37/lib/python3.7/typing.py", …Run Code Online (Sandbox Code Playgroud) 我对Python模块的用例不是很熟悉__future__,只是我在一些在线文章的演示代码中看到过它。读完之后,我想这与面向未来的现有代码有关?我承认我并不完全理解我正在读的内容。根据官方文档,其功能为:
\n\n\n
\n- 为了避免混淆分析导入语句并期望找到它们\xe2\x80\x99正在导入的模块的现有工具。
\n- 为了确保 future 语句在 2.1 之前的版本下运行至少会产生运行时异常(future的导入将会失败,因为在 2.1 之前没有该名称的模块)。
\n- 记录何时引入不兼容的更改,以及何时将这些更改强制为 \xe2\x80\x94 或 \xe2\x80\x94。这是一种可执行文档的形式,可以通过导入future并检查其内容以编程方式进行检查。
\n
第1点是什么意思?是不是说如果解释器读取导入语句,但没有找到它正在导入的模块,那么拥有import __future__将阻止它抛出错误?
随着 Python 2.7 于 2020 年 1 月 1 日正式终止,如果我无意在我的 Python 3 代码中支持 Python 2 环境,那么我认为第 2 点与我无关。
\n我猜第 3 点是为了……调试?这就是它想表达的吗?
\n我注意到到目前为止我读过的所有文章都至少是五年前的。所有示例都重点关注处理 Python 2 向后兼容性的 Python 3 代码,特别print是//. 但正如我所说,我无意支持 Python 2。
Python 中 __future__ 的用途是什么,如何/何时使用它,以及它是如何工作的
\nimport __future那么,如果不打算向后兼容 Python 2,我什么时候需要在 …
更具体:
要解决诸如如何使用封闭类的类型键入提示方法之类的问题?
PEP 673介绍typing.Self。PEP 是一个草案,但目前它是 Typing_extensions 4.0.0 中的实验类型
我尝试在 python 3.8 中使用它
@dataclasses.dataclass
class MenuItem:
url: str
title: str
description: str = ""
items: typing.List[typing_extensions.Self] = dataclasses.field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)
但它提高了
TypeError: Plain typing_extensions.Self is not valid as type argument
Run Code Online (Sandbox Code Playgroud)
我可以只使用文字字符串“MenuItem”来代替。但我想知道为什么这不起作用。
我正在玩python的3.5类型提示.我想知道如何键入提示类方法的返回类型.
这就是我的想法:
>>> class A():
@classmethod
def a(cls) -> A:
pass
Traceback (most recent call last):
File "<pyshell#24>", line 1, in <module>
class A():
File "<pyshell#24>", line 3, in A
def a(cls) -> A:
NameError: name 'A' is not defined
Run Code Online (Sandbox Code Playgroud)
显然它不起作用.我想一种方法是做某种"前向声明",如下所示:
>>> class A():
pass
>>> class A():
@classmethod
def a(cls) -> A:
pass
Run Code Online (Sandbox Code Playgroud)
但这并不觉得"pythonic".人们通常如何解决这个问题?
下面的类有一个类方法create(),它作为返回类型的类型提示,用于创建该类的实例。
class X:
@classmethod
def create(cls) -> X:
pass
Run Code Online (Sandbox Code Playgroud)
然而,却出现了以下错误?
名称错误:名称“X”未定义
我一直在研究类型提示我的代码,但注意到 Python 程序员通常不会self在他们的程序中键入提示
即使我查看文档,它们似乎也没有输入提示 self,请参见 此处。这是来自 3.10 版的前向声明
def __init__(self, value: T, name: str, logger: Logger) -> None:
Run Code Online (Sandbox Code Playgroud)
我可以理解为什么在 3.7 中引入带有前向声明的类型注释之前,这是一个问题
这对我来说似乎有用的原因是 mypy 似乎能够捕捉到这个问题的错误
例子:
from __future__ import annotations
class Simple(object):
def __init__(self: Simple):
print(self.x)
Run Code Online (Sandbox Code Playgroud)
将从 mypy 返回这个
mypy test.py
test.py:5: error: "Simple" has no attribute "x"
Found 1 error in 1 file (checked 1 source file)
Run Code Online (Sandbox Code Playgroud)
如果您从中删除类型,则self变为
Success: no issues found in 1 source file
Run Code Online (Sandbox Code Playgroud)
self未注释的原因,或者这是唯一的约定?self …我正在编写一个 CustomEnum 类,我想在其中添加一些辅助方法,然后子类化我的 CustomEnum 的类可以使用这些方法。其中一种方法是返回一个随机枚举值,这就是我被卡住的地方。该函数按预期工作,但在类型提示方面,我无法想出一种说法“返回类型与 cls 类型相同”。
我相当确定其中TypeVar涉及一些或类似的魔法,但由于我从未使用过它们,因此我从未花时间弄清楚它们。
class CustomEnum(Enum):
@classmethod
def random(cls) -> ???:
return random.choice(list(cls))
class SubclassingEnum(CustomEnum):
A = "a"
B = "b"
random_subclassing_enum: SubclassingEnum
random_subclassing_enum = SubclassingEnum.random() # Incompatible types in assignment (expression has type "CustomEnum", variable has type "SubclassingEnum")
Run Code Online (Sandbox Code Playgroud)
有人可以帮助我或给我一个关于如何进行的提示吗?
谢谢!
python ×9
type-hinting ×3
mypy ×2
python-3.x ×2
annotations ×1
pycharm ×1
pylint ×1
python-3.5 ×1