类型暗示返回 self 的类方法的返回值?

2023-11-27

正如问题所描述的,我想输入提示aself返回,类似:

class A:
    def foo(self) -> [what goes here?]:
        # do something
        return self

我已经尝试过的事情:

  1. 将其注释为A(添加from __future__ import annotations在顶部):这意味着该方法返回一个实例化的A()对象,不一定self.
  2. 将其注释为Type[A](添加from typing import Type): 这意味着该方法正在返回一个未实例化的A,距离并不远self.
  3. 注释为Self(添加from typing_extensions import Self): mypy 给出错误:Variable "typing_extensions.Self" is not valid as a type [valid-type]mypy(error)

可能有帮助的事情:将鼠标悬停在方法上foo没有返回值的注释,VScode提示显示——Self@A,我不明白,但是,这绝对区别于返回另一个实例化类A()并返回self... 谢谢


我找不到任何详细涵盖这一点的问题,因此将尝试解释。

对于类型检查来说“相同类型”意味着什么

好吧,这可能是“你不能,也不应该”的长形式。

类型检查的目的是确认所有函数都使用正确的参数类型调用并返回预期的类型。我建议阅读PEP483首先要理解概念type更好的。假设您有以下内容:

s1 = ''.join(['a', 'b', 'c'])
s2 = ''.join(['a', 'b', 'c'])
assert s1 is not s2
assert s1 == s2

(join以避免优化,但这是另一个故事)。它们是同一个对象吗?不,is not清楚地说明了这一点(它们具有不同的内存地址)。但会s2随时可以接受s1?绝对是的。您不会创建仅在以下位置运行的函数s1并检查这个事实is, right?

现在是什么不同之处之间self作为对确切对象的引用和self as any A实例?当我们谈论类型检查时,所有A实例是完全等价且不可区分的。它们具有相同的方法和属性集(包括类型)。我们可以问:“如果我们显式声明对象为self实例而不仅仅是self类型?”我真的想不出任何类型。如果你想要这个语义,请使用文档字符串 - 类型不应该被滥用于所有事情。self对象与任何其他对象完全相同A()类型检查器的实例。

简单的解决方案:返回类实例

您的第一个代码示例几乎没问题。将返回注释为A告诉它返回类的实例A,它将适用于最后一堂课:

class A:
    def foo(self) -> A:
        return self

然而,这种方法有一个缺点(在 PEP673 中很好地解释了Self type):

class AChild(A):
    pass

# mypy
reveal_type(AChild().foo())  # N: revealed type is "__main__.A"

如果您创建新的A in foo并返回,那么这个方法就完美了。如果你return self- 它是有效的,但不精确。这就是为什么我们需要Self type.

Self type

Self类型被引入PEP673,并且不被支持mypy在撰写本文时。 (更新:自支持以来mypy 1.0发布于 2023 年 2 月 6 日)您在第三个示例中的用法完全有效,并且在类型检查器中实现后将起作用(请参阅 PEP 的“动机”部分中的第 5 个代码块)。该支持已添加到mypy在版本中1.0,所以如果您使用此版本或更高版本 - 本节是正确的答案。

以下是您可以使用的方法Self(假设python=3.11不去打扰typing_extensions):

from typing import Self

class A:
    def foo(self) -> Self:
        return self

class AChild(A):
    pass

# mypy
reveal_type(AChild().foo())  # N: revealed type is "__main__.AChild"
reveal_type(A().foo())  # N: revealed type is "__main__.A"

实施Self键入而不使用它

不过,你可以模仿Self准确地用几行代码(和python >= 3.7, 公平)。

from typing import TypeVar

_Self = TypeVar('_Self', bound='A')

class A:
    def foo(self: _Self) -> _Self:
        return self

class AChild(A):
    pass

# mypy
reveal_type(AChild().foo())  # N: revealed type is "__main__.AChild"
reveal_type(A().foo())  # N: revealed type is "__main__.A"

现在这有效了。所有子类都会返回它们的类实例。

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

类型暗示返回 self 的类方法的返回值? 的相关文章

随机推荐

  • 量角器切换到上一个选项卡

    打开新选项卡 第二个 后 我尝试切换到第一个选项卡 common clickOpenNewSession it opens the new tab browser getAllWindowHandles then function hand
  • 在 Java ME 中将 JSON 字符串转换为对象?

    Java J2ME中有没有办法转换字符串 例如 name MyNode width 200 height 100 在一行代码中转换为相同的内部对象表示 因为目前的方法太繁琐了 Object n create new setString p
  • Clojure Web 应用程序的良好 Web 服务器/Servlet 容器?

    我正在为我的 compojure Web 应用程序寻找一个好的生产 Web 服务器 servlet 容器 对于使用 compojure 的 Clojure Web 应用程序 使用 Jetty 或 Tomcat 或其他服务器有何优缺点 有没有
  • IIS ASP.Net 网站 - ManagedPipelineHandler 错误(尝试在不存在的网络连接上执行操作)

    我遇到一个奇怪的问题 我有一个使用表单身份验证的 ASP Net Web 应用程序 如果我打开登录页面并且有几分钟处于非活动状态 则登录尝试超时或 IE FireFox 显示 无法显示此页面 如果没有暂停或缺乏活动 则没有问题并且网站按预期
  • 如何在 LLVM 中打印字符串

    我想将 LLVM 中的指令打印到字符串而不是屏幕上 我用I gt print errs 打印到屏幕上 我怎样才能将指令放入字符串中 像这样 std string str llvm raw string ostream rso str I g
  • 如何停止Memo控件的自动滚动?

    在 Windows 7 中 备忘录控件 TMemo 插入文本后会自动滚动 Memo Lines Add Path 这是我不想要的 因为滚动是我自己完成的 如何停止自动滚动 通常 向备忘录控件添加文本会将备忘录滚动到插入文本的底部 为了防止这
  • Objective-C 接口、委托和协议

    因此 我试图了解 Objective C 接口 委托和协议 所以我有一个问题 委托是否必须位于单独的文件中 或者可以是类中定义的方法吗 协议类似于java接口吗 这就是我目前的理解方式 如果你使用这个协议 它基本上会让你实现方法 我仍然对接
  • 外键与辅助键

    我曾经认为外键和辅助键是同一个东西 谷歌搜索后 结果更加令人困惑 有些人认为它们是相同的 另一些人则说辅助键是一个不必是唯一的索引 并且允许比主键更快地访问数据 有人可以解释其中的区别吗 或者这确实是一个混合术语的情况 每个数据库类型可能有
  • Math.Round 与 String.Format

    我需要将双精度值四舍五入为 2 位数字 什么是更好的 String Format 0 0 00 123 4567 123 46 Math Round 123 4567 2 123 46 Math Round double digits 数字
  • 改善 Flexbox 生产线的平衡

    举例来说 假设我有一个弹性盒 其中每个元素都包含一个图像 在这种情况下 Flexbox 的目的是均匀分布它们 看起来很容易 我们来试试吧 flex width 350px display flex flex wrap wrap flex g
  • javascript:检测滚动结束

    我有一个div层与overflow set to scroll 当滚动到底部时div 我想运行一个函数 接受的答案从根本上来说是有缺陷的 现已被删除 正确答案是 function scrolled e if myDiv offsetHeig
  • 使用动态字段名称更新模型实例

    我想做的很简单 f Foobar objects get id 1 foo somefield bar somevalue f foo bar f save 这不起作用 因为它尝试更新 f 对象的 foo 字段 该字段当然不存在 我怎样才能
  • 创建 MySQL 触发器的 SQL 语法错误

    我尝试创建触发器 CREATE TRIGGER aster users2 after update ON aster users FOR EACH ROW BEGIN update event set flag 1 where id 1 E
  • 使用 Unity 解决命名依赖关系

    我有一个具有 2 个依赖项的服务 一个存储库和一个网关 短信 我需要解析该服务的 2 个不同版本 它们仅在传递给网关的参数之一上有所不同 代码简化如下 public interface IService string DoSomething
  • 将任意字符串映射到 RGB 值

    我有一大堆任意自然语言字符串 对于我的工具来分析它们 我需要将每个字符串转换为唯一的颜色值 RGB 或其他 我需要颜色对比来取决于字符串相似性 字符串与其他字符串越不同 它们各自的颜色应该越不同 如果我总是为同一字符串获得相同的颜色值 那就
  • LoadString 仅在我没有英文字符串表时才有效

    我希望能够以编程方式修改应用程序的语言 或者至少使用 控制面板 gt 区域和语言选项 gt 格式 中指定的语言 如果我添加一个英语字符串表 为其制作一个法语和德语副本 然后删除英语字符串表 我可以以编程方式在加载法语和德语字符串之间切换 如
  • JavaScript 中的大数字字符串

    当我执行以下操作时 alert 2053716830872415770228778006271971120334843128349550587141047275840274143041 toString 我得到 2 053716830872
  • Google App脚本从网站提取数据

    所以我正在写一个脚本来查看在 Google 信息页上完成审核并更新谷歌电子表格 我发现html中保存这个值的行是 span class A7a 103 span 我只需要知道 URL 和 html 代码就可以从页面中提取内容 Use var
  • 如何包含 MVC 部分控件中的 css 文件?

    我正在使用 ASP NET MVC 并且有一个需要包含特定 CSS 和 JS 文件的部分控件 有没有办法让父页面渲染script and link页面 head 部分中的标签 而不是仅仅在部分控件中内联渲染它们 为了澄清我想要包含文件的控件
  • 类型暗示返回 self 的类方法的返回值?

    正如问题所描述的 我想输入提示aself返回 类似 class A def foo self gt what goes here do something return self 我已经尝试过的事情 将其注释为A 添加from future