如何在子类中键入注释重写的方法?

2024-03-25

假设我已经有一个带有类型注释的方法:

class Shape:
    def area(self) -> float:
        raise NotImplementedError

然后我将对其进行多次子类化:

class Circle:
    def area(self) -> float:
        return math.pi * self.radius ** 2

class Rectangle:
    def area(self) -> float:
        return self.height * self.width

正如你所看到的,我正在复制-> float非常多。假设我有 10 种不同的形状,有多种这样的方法,其中一些也包含参数。有没有办法从父类中“复制”注释,类似于functools.wraps()与文档字符串有关吗?


这可能会起作用,尽管我肯定会错过边缘情况,例如附加参数:

from functools import partial, update_wrapper


def annotate_from(f):
    return partial(update_wrapper,
                   wrapped=f,
                   assigned=('__annotations__',),
                   updated=())

这将分配“包装”函数的__annotations__属性来自f.__annotations__(请记住,它不是副本)。

根据文件显示update_wrapper https://docs.python.org/3/library/functools.html#functools.update_wrapper函数的默认值是assigned包括__annotations__已经,但我可以明白为什么您不想将所有其他属性分配给wrapped.

这样您就可以定义您的Circle and Rectangle as

class Circle:
    @annotate_from(Shape.area)
    def area(self):
        return math.pi * self.radius ** 2

class Rectangle:
    @annotate_from(Shape.area)
    def area(self):
        return self.height * self.width

和结果

In [82]: Circle.area.__annotations__
Out[82]: {'return': builtins.float}

In [86]: Rectangle.area.__annotations__
Out[86]: {'return': builtins.float}

作为副作用,你的方法将有一个属性__wrapped__,这将指向Shape.area在这种情况下。


一个不太标准的(如果你可以调用上面的使用更新包装器标准)方法可以使用类装饰器来实现处理重写方法:

from inspect import getmembers, isfunction, signature


def override(f):
    """
    Mark method overrides.
    """
    f.__override__ = True
    return f


def _is_method_override(m):
    return isfunction(m) and getattr(m, '__override__', False)


def annotate_overrides(cls):
    """
    Copy annotations of overridden methods.
    """
    bases = cls.mro()[1:]
    for name, method in getmembers(cls, _is_method_override):
        for base in bases:
            if hasattr(base, name):
                break

        else:
            raise RuntimeError(
                    'method {!r} not found in bases of {!r}'.format(
                            name, cls))

        base_method = getattr(base, name)
        method.__annotations__ = base_method.__annotations__.copy()

    return cls

进而:

@annotate_overrides
class Rectangle(Shape):
    @override
    def area(self):
        return self.height * self.width

同样,这不会处理带有附加参数的重写方法。

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

如何在子类中键入注释重写的方法? 的相关文章

随机推荐

  • 这个特权准则有什么问题吗?

    如何检查 检查 php代码或页面中的权限 我使用爆炸和 in array 用户登录并进入 检查 页面后 代码必须检查用户的权限是否具有 dataDisplay 权限 但 检查 页面中的代码不会执行此操作 我的 检查 页面代码有什么问题 这是
  • Windows10 上使用 VirtualBox 的 Vagrant:在您的 PATH 中找不到“Rsync”

    我在 Windows 7 系统上使用 Vagrant 一段时间了 现在我有一台装有 Windows 10 的新 PC 我安装了 Oracle Virtual Box 和 Vagrant 并尝试使用命令 vagrant up 启动计算机 Va
  • r 中的 ifelse 匹配向量

    我有一个如下所示的数据框 gt df lt data frame A c NA 1 2 3 4 B c NA 5 2 6 4 C c NA NA 2 NA NA gt df A B C 1 NA NA NA 2 1 5 NA 3 2 2 2
  • C/C++ 的多线程内存分配器

    我目前有大量的多线程服务器应用程序 并且我正在寻找一个好的多线程内存分配器 到目前为止 我在以下两点之间左右为难 太阳乌梅 谷歌的tcmalloc 英特尔的线程构建块分配器 埃默里 伯杰的宝藏 据我所知 hoard 可能是最快的 但我在今天
  • 为什么冒泡排序最好情况的时间复杂度是O(n)

    我按照书中使用的方法推导了冒泡排序在最佳情况下的时间复杂度算法2 2 但结果是 O n 2 以下是我的推导 希望大家帮我找出哪里错了 public void bubbleSort int arr for int i 0 len arr le
  • 让 Kotlin 序列化器与 Retrofit 配合使用

    我无法让 Kotlin Serializer 与 Retrofit 一起使用 我在用com jakewharton retrofit retrofit2 kotlinx serialization converter 0 5 0与 Retr
  • 如何用networkx绘制社区

    如何使用 python networkx 绘制其社区的图表 如下图所示 图片网址 https data graphstream project org talks CSSS2012 media Community Structure2 jp
  • Pentaho Data Integration(最新版本)-未检测到 MySQL 驱动程序

    我是这个工具的新手 我正在尝试创建与数据库的 MySQL 连接 但是当我按下 测试 按钮时 它会显示以下消息 Error connecting to database MySQL configuracionesEF org pentaho
  • 将 UITableView 作为容器视图嵌入到 UIViewController 中

    我想添加一个文本字段和发送按钮 该按钮粘贴在 uitableview 的底部 类似于聊天应用程序 我遇到过关于将 UITableView 作为容器视图嵌入到 UIViewController 中的评论 然而 他们似乎缺乏如何实现这一目标的例
  • 自应用签名后文档已被更改或损坏 itext 5.5.11

    基本上 我收到错误 自应用签名以来文档已被更改或损坏 我按照 itext 网站的示例并根据我的情况进行了调整 准备好要签名的文档 添加append模式 因为可以 已经签署的文件 调用 Web 服务来签署哈希值 将签名哈希添加到准备好的文档中
  • 如何在 Django 中验证电子邮件地址? [复制]

    这个问题在这里已经有答案了 我编写了一个用于将电子邮件添加到时事通讯库的函数 在我添加检查发送电子邮件的有效性之前 它一直运行得很好 现在每次我都会收到 错误的电子邮件 回复 有人能看到这里有任何错误吗 使用的正则表达式是 b w w w
  • 在 Pandas DataFrame 中拆分列列表

    我正在寻找解决以下问题的好方法 我当前的修复不是特别干净 我希望从您的见解中学习 假设我有一个 Panda DataFrame 其条目如下所示 gt gt gt df pd DataFrame index 1 2 3 columns Col
  • 两个3D点云变换矩阵

    我试图猜测两个 3D 点云之间的刚性变换矩阵是哪个 这两个点云是 来自 kinect 的关键点 kinect keypoints 来自 3D 对象 盒子 的关键点 object keypoints 我尝试过两种选择 1 实现寻找刚性变换的算
  • 为什么 PyPy 翻译这么慢?

    将 pypy 实现转换为 c 文件并在具有 2G mem 和 Intel Core2 2GHz CPU 的现代笔记本电脑上构建 pypy c 需要几个小时 我知道这是一个 CPU 密集型任务 但是有必要这么慢吗 有没有机会或者空间来减少计算
  • Rails 3 时区错误

    我在 Rails 3 beta 中的时区支持方面遇到了困难 我想知道这是否是一个错误 或者我是否做错了什么 他就是问题所在 gt Time zone Madrid it is GMT 2 gt Madrid gt c Comment new
  • 如何测试一个对象是否是一个可以接受 jQuery 中的 .each() 的集合?

    如何测试一个对象是否是一个可以接受 jQuery 中的 each 的集合 提前致谢 试长度 if my class length gt 1 http jsfiddle net AlienWebguy QhFDN http jsfiddle
  • WOPI 主机未呼叫

    我想知道为什么我的 WOPI 主机没有被呼叫 我通过类似于以下内容的 HTML 页面启动我的主机 https github com Microsoft Office Online Test Tools and Documentation b
  • warpPerspective和perspectiveTransform有什么区别?

    我使用了四组点来获得透视变换矩阵 然后使用warpPerspective变换矩阵A到矩阵B Mat A 中的点 a 我想在 mat B 中获得新点的位置 但是warpPerspective不能那样做 同时perspectiveTransfo
  • 使用Maven安装Bower组件并全局安装Bower

    我使用 NPM 在全球范围内安装了 Bower 在我的 Maven 项目中 我有一个 Bower json 文件 我使用 exec maven plugin 在构建时安装 Bower 组件 但是它失败了 因为它 无法在目录中运行程序 bow
  • 如何在子类中键入注释重写的方法?

    假设我已经有一个带有类型注释的方法 class Shape def area self gt float raise NotImplementedError 然后我将对其进行多次子类化 class Circle def area self