使用元类覆盖复杂内置方法

2024-03-30

作为学习练习,我正在尝试实现一个类来模拟 python 的行为complex内置的,但具有不同的行为__str__ and __repr__方法:我希望它们以以下格式打印...

(1.0,2.0)

...代替:

(1+2j)

我首先尝试简单地从complex并重新定义__str__ and __repr__,但这有一个问题,当调用非重写方法时,标准complex返回并以标准格式打印:

>>> a = ComplexWrapper(1.0,1.0)
>>> a
(1.0,1.0)
>>> b = ComplexWrapper(2.0,3.0)
>>> b
(2.0,3.0)
>>> a + b
(3+4j)

当所需的输出为(3.0,4.0).

我正在阅读有关元类的内容,并认为它们可以解决我的问题。从答案开始Python 类装饰器 https://stackoverflow.com/questions/681953/python-class-decorator,我目前的实现如下:

def complex_str(z):
    return '(' + str(z.real) + ',' + str(z.imag) + ')'
def complex_repr(z):
    return '(' + repr(z.real) + ',' + repr(z.imag) + ')'

class CmplxMeta(type):
    def __new__(cls, name, bases, attrs):
        attrs['__str__'] = complex_str
        attrs['__repr__'] = complex_repr
        return super(CmplxMeta, cls).__new__(cls, name, bases, attrs)

class ComplexWrapper(complex):
    __metaclass__ = CmplxMeta

不幸的是,这似乎与之前的解决方案具有相同的行为(例如,当两个ComplexWrapper实例相互添加)。

我承认,我并不完全理解元类。也许我的问题可以用不同的方式解决?

当然,我可以手动重新定义相关方法,例如__add__, __subtract__等等。但这会非常重复,所以我更喜欢更优雅的解决方案。

任何帮助表示赞赏。


编辑:对 agf 答案的回应:

所以我对你的代码有很多不明白的地方:

  1. 哪里有__new__的方法ReturnTypeWrapper元类从哪里获取它的参数?如果它们自动通过,我希望在这种情况下name = "Complex", bases = (complex), dict = {}。那是对的吗?这种自动传递类数据的方法是否特定于元类?

  2. 你为什么使用cls = type.__new__(mcs, name, bases, dct)代替cls = type(mcs, name, bases, dct)? 难道只是为了避免与“其他含义”混淆type()?

  3. 我复制了你的代码,并添加了我的特殊实现__str__ and __repr__在你的ComplexWrapper班级。但这不起作用;打印任何类型的对象Complex仅以标准 Python 格式打印。我不明白这一点,因为这两个方法应该在元类的 for 循环中选取,但之后应该被我的定义覆盖。

我的代码的相关部分:

class Complex(complex):
    __metaclass__ = ReturnTypeWrapper
    wrapped_base = complex
    def __str__(self):
        return '(' + str(self.real) + ',' + str(self.imag) + ')'
    def __repr__(self):
        return '(' + repr(self.real) + ',' + repr(self.imag) + ')'

及其行为:

>>> type(a)
<class 'Cmplx2.Complex'>
>>> a.__str__
<bound method Complex.wrapper of (1+1j)>
>>> a.__str__()
'(1+1j)'
>>> 

再次感谢您的回答,如果您在答案中解决了上述问题,请随时编辑/删除以上内容!


你现在的方法行不通。如何定义类不是问题——方法complex正在创建新实例complex当你打电话给他们时,而不是使用type输入对象的数量。你总是会得到以下实例complex而不是ComplexWrapper,因此您的自定义方法将不会被调用:

>>> type(ComplexWrapper(1.0,1.0) + ComplexWrapper(2.0,3.0))
<type 'complex'>

相反,您需要转换新的complex的方法返回的对象complex返回派生类的对象。

该元类包装指定基类的所有方法,并将包装的方法附加到该类。包装器检查要返回的值是否是基类的实例(但不包括子类的实例),如果是,则将其转换为派生类的实例。

class ReturnTypeWrapper(type):
    def __new__(mcs, name, bases, dct):
        cls = type.__new__(mcs, name, bases, dct)
        for attr, obj in cls.wrapped_base.__dict__.items():
            # skip 'member descriptor's and overridden methods
            if type(obj) == type(complex.real) or attr in dct:
                continue
            if getattr(obj, '__objclass__', None) is cls.wrapped_base:
                setattr(cls, attr, cls.return_wrapper(obj))
        return cls

    def return_wrapper(cls, obj):
        def convert(value):
            return cls(value) if type(value) is cls.wrapped_base else value
        def wrapper(*args, **kwargs):
            return convert(obj(*args, **kwargs))
        wrapper.__name__ = obj.__name__
        return wrapper

class Complex(complex):
    __metaclass__ = ReturnTypeWrapper
    wrapped_base = complex
    def __str__(self):
        return '({0}, {1})'.format(self.real, self.imag)
    def __repr__(self):
        return '{0}({1!r}, {2!r})'.format(self.__class__.__name__, 
                                          self.real, self.imag)


a = Complex(1+1j)
b = Complex(2+2j)

print type(a + b)

请注意,这不会包装__coerce__特殊方法,因为它返回一个tuple of complexs;如果需要,可以轻松地将包装器转换为查看序列内部。

The __objclass__未绑定方法的属性似乎没有记录,但它指向定义该方法的类,因此我用它来过滤掉在我们要转换的类之外的类上定义的方法。我还在这里使用它来过滤掉不是未绑定方法的属性。

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

使用元类覆盖复杂内置方法 的相关文章

  • 如何使用 opencv.omnidir 模块对鱼眼图像进行去扭曲

    我正在尝试使用全向模块 http docs opencv org trunk db dd2 namespacecv 1 1omnidir html用于对鱼眼图像进行扭曲处理Python 我正在尝试适应这一点C 教程 http docs op
  • 安装了 32 位的 Python,显示为 64 位

    我需要运行 32 位版本的 Python 我认为这就是我在我的机器上运行的 因为这是我下载的安装程序 当我重新运行安装程序时 它会将当前安装的 Python 版本称为 Python 3 5 32 位 然而当我跑步时platform arch
  • Pandas/Google BigQuery:架构不匹配导致上传失败

    我的谷歌表中的架构如下所示 price datetime DATETIME symbol STRING bid open FLOAT bid high FLOAT bid low FLOAT bid close FLOAT ask open
  • 用枢轴点拟合曲线 Python

    我有下面的图 我想用 2 条线来拟合它 使用 python 我设法适应上半部分 def func x a b x np array x return a x b popt pcov curve fit func up x up y 我想用另
  • 使用字典映射数据帧索引

    为什么不df index map dict 工作就像df column name map dict 这是尝试使用index map的一个小例子 import pandas as pd df pd DataFrame one A 10 B 2
  • 为什么 PyYAML 花费这么多时间来解析 YAML 文件?

    我正在解析一个大约 6500 行的 YAML 文件 格式如下 foo1 bar1 blah name john age 123 metadata whatever1 whatever whatever2 whatever stuff thi
  • Python beautifulsoup 仅限 1 级文本

    我看过其他 beautifulsoup 得到相同级别类型的问题 看来我的有点不同 这是网站 我正试图拿到右边那张桌子 请注意表的第一行如何展开为该数据的详细细分 我不想要那个数据 我只想要最顶层的数据 您还可以看到其他行也可以展开 但在本例
  • pyspark 将 twitter json 流式传输到 DF

    我正在从事集成工作spark streaming with twitter using pythonAPI 我看到的大多数示例或代码片段和博客是他们从Twitter JSON文件进行最终处理 但根据我的用例 我需要所有字段twitter J
  • Cython 和类的构造函数

    我对 Cython 使用默认构造函数有疑问 我的 C 类 Node 如下 Node h class Node public Node std cerr lt lt calling no arg constructor lt lt std e
  • 加快网络抓取速度

    我正在使用一个非常简单的网络抓取工具抓取 23770 个网页scrapy 我对 scrapy 甚至 python 都很陌生 但设法编写了一个可以完成这项工作的蜘蛛 然而 它确实很慢 爬行 23770 个页面大约需要 28 小时 我看过scr
  • javascript 是否有等效的 __repr__ ?

    我最接近Python的东西repr这是 function User name password this name name this password password User prototype toString function r
  • Jupyter Notebook 找不到 Python 模块

    不知道发生了什么 但每当我使用 ipython 氢 原子 或 jupyter 笔记本时都找不到任何已安装的模块 我知道我安装了 pandas 但笔记本说找不到 我应该补充一点 当我正常运行脚本时 python script py 它确实导入
  • pip 列出活动 virtualenv 中的全局包

    将 pip 从 1 4 x 升级到 1 5 后pip freeze输出我的全局安装 系统 软件包的列表 而不是我的 virtualenv 中安装的软件包的列表 我尝试再次降级到 1 4 但这并不能解决我的问题 这有点类似于这个问题 http
  • Python3 在 DirectX 游戏中移动鼠标

    我正在尝试构建一个在 DirectX 游戏中执行一些操作的脚本 除了移动鼠标之外 我一切都正常 是否有任何可用的模块可以移动鼠标 适用于 Windows python 3 Thanks I used pynput https pypi or
  • import matplotlib.pyplot 给出 AttributeError: 'NoneType' 对象没有属性 'is_interactive'

    我尝试在 Pycharm 控制台中导入 matplotlib pyplt import matplotlib pyplot as plt 然后作为回报我得到 Traceback most recent call last File D Pr
  • 如何使用原始 SQL 查询实现搜索功能

    我正在创建一个由 CS50 的网络系列指导的应用程序 这要求我仅使用原始 SQL 查询而不是 ORM 我正在尝试创建一个搜索功能 用户可以在其中查找存储在数据库中的书籍列表 我希望他们能够查询 书籍 表中的 ISBN 标题 作者列 目前 它
  • Pandas 将多行列数据帧转换为单行多列数据帧

    我的数据框如下 code df Car measurements Before After amb temp 30 268212 26 627491 engine temp 41 812730 39 254255 engine eff 15
  • 如何解决 PDFBox 没有 unicode 映射错误?

    我有一个现有的 PDF 文件 我想使用 python 脚本将其转换为 Excel 文件 目前正在使用PDFBox 但是存在多个类似以下错误 org apache pdfbox pdmodel font PDType0Font toUnico
  • python import inside函数隐藏现有变量

    我在我正在处理的多子模块项目中遇到了一个奇怪的 UnboundLocalError 分配之前引用的局部变量 问题 并将其精简为这个片段 使用标准库中的日志记录模块 import logging def foo logging info fo
  • Pandas 每周计算重复值

    我有一个Dataframe包含按周分组的日期和 ID df date id 2022 02 07 1 3 5 4 2022 02 14 2 1 3 2022 02 21 9 10 1 2022 05 16 我想计算每周有多少 id 与上周重

随机推荐

  • Amazon AWS Fargate 任务静态 IP 地址

    在 AWS 上迁移期间 我在 AWS 上创建了一个新集群 并使用 Fargate 方法部署了多个 docker 应用程序 每次更新任务定义期间 都会在服务内启动新任务 并从 AWS 公共 IP 池分配新的公共 IP 有没有关于如何将静态 I
  • 如何更改 NSTimer 的计时?

    我有以下代码 timer NSTimer scheduledTimerWithTimeInterval 0 50 target self selector selector onTimer userInfo nil repeats YES
  • 在 ASP.NET MVC Web 应用程序中包含预编译视图

    在 ASP NET MVC Web 应用程序中包含预编译视图 参考 http ofps oreilly com titles 9781449320317 ch ReusableUI html 请参阅上面的博客 我正在尝试在 MVC 3 中创
  • LMAX Disruptor最简单、最实际的示例代码

    我希望我能得到最简单的示例代码 它将展示如何使用 LMAX Disruptor http code google com p disruptor 不幸的是 每一段代码都已经过时了 有人知道 我在哪里可以找到最新的小指南 最好没有 DSL 这
  • EntityFramework 同表多对多关系

    我有一个名为 产品 的表 其中显然包含产品 但是 我需要创建相关产品 所以我所做的就是创建一个名为product related 的连接表 它有两个PK ProductID 来自 Products 表 RelatedID 也来自 Produ
  • 我可以在 Android 开发中使用 javax.script 吗?如果可以,如何使用?

    我在包含 javax script 时遇到了一些麻烦在 Android 项目中 我需要它 这样我就可以在 JavaScript 中使用 eval 函数 以便有效地解析算术函数 而无需自己构建解析器 我在这方面完全没有经验 也没有很多时间 我
  • 确定我的 App Engine 代码正在哪个项目 ID 上运行

    在 App Engine 应用程序中 有没有办法确定 GAE App Engine 实例正在运行的项目 ID 我想访问运行 App Engine 实例的同一项目中的大型查询表 如果可能的话 我不想对其进行硬编码或将其包含在另一个配置文件中
  • Prolog 程序从列表中删除每个第 n 个元素

    您能帮我解决以下问题吗 编写三元谓词delete nth从列表中删除每个第 n 个元素 样本运行 delete nth a b c d e f 2 L L a c e false delete nth a b c d e f 1 L L f
  • JavaFX 2 自动列宽

    我有一个 JavaFX 2 表 显示人们的联系方式 假设有三列 名字 姓氏和电子邮件地址 当我的应用程序启动时 它会在表中填充有关系统中已有人员的几行数据 问题是列宽都是相同的 大多数时候 名字和姓氏会完整显示 但电子邮件地址会被剪掉 用户
  • 两个属性与一个实体共享相同的 OneToMany 关系 Symfony2

    首先描述一下我的情况 我正在使用 Symfony2 但我的实体之间的关系存在问题 我有两个链接在一起的实体 这两个实体是AssociationQuestion and AssociationPossibleAnswer 我目前正在创建一个调
  • Java && ||在 RETURN 语句中?

    我正在查看一些 Java 算法示例 并且在递归方法中遇到了以下代码片段 boolean subTree TreeNode t1 TreeNode t2 if t1 null return false if t1 value t2 value
  • 如何检查浏览器对功能/事件的支持?

    过去 我们使用浏览器嗅探来推断某些事件或功能是否可用 据我所知 浏览器嗅探已被 弃用 或 回避 取而代之的是功能嗅探 我想知道如何检查是否可以处理某个事件 Take DOMNodeInserted例如 Chrome FF 和 Safari
  • 地图首次加载时如何自动打开地图上的注释标注?

    我正在开发一个基于 iPhone 的导航应用程序 它允许用户在地图上查看表格中的选择 我有一个注释可以精确定位用户在地图上选择的位置 按照正常行为 如果用户单击注释 则会出现一个标注 其中包含有关位置的详细信息 这里没有问题 我的问题是 一
  • Lime的R版本可以用count:poisson目标函数解释xgboost模型吗?

    我使用 xgb train 和 count poisson 目标函数生成了一个模型 在尝试创建解释器时出现以下错误 Error Unsupported model type 当我用其他东西 例如 reg logistic 替换目标时 Lim
  • HTML CSS 表单 - 如何使表单在​​页面上居中?

    我制作了一个表单 试图将其置于页面中心 但它不起作用 我尝试将这 2 个 CSS 应用于它 但没有成功 form margin 0 auto form margin auto 我还尝试将表单封装到 div container 中并对其应用相
  • 下载 ASP.NET MVC C# 中字节数组列表中包含的多个文件

    我正在开发一个 ASP NET MVC 5 应用程序 我编写了一个代码 允许我下载存储在 SQL Server 数据库中的文件 varbinary 我可以使用以下命令下载单个文件 public JsonResult PrepareSingl
  • 如何将公历转换为中国农历?

    我想使用公历到中国农历构建一个Android应用程序 我不知道如何从公历转换为农历 我怎样才能做到这一点 从公历到中文的转换 我刚刚发布了Time4J的新版本 v4 35 但是使用Time4A https github com MenoDa
  • 在caffe中定义新层时如何获取学习率或迭代次数

    我想当迭代次数达到一定次数时改变损失层中的损失计算方法 为了实现它 我认为我需要获取当前的学习率或迭代次数 然后我使用if短语选择是否改变损失计算方法 您可以添加一个成员变量咖啡类保存当前的学习率或迭代次数并在您想要的层中访问它 例如 要获
  • 如何从命令行删除钥匙串引用

    From the Keychain app I have the option to delete just the reference to a listed Keychain that was unlocked and listed v
  • 使用元类覆盖复杂内置方法

    作为学习练习 我正在尝试实现一个类来模拟 python 的行为complex内置的 但具有不同的行为 str and repr 方法 我希望它们以以下格式打印 1 0 2 0 代替 1 2j 我首先尝试简单地从complex并重新定义 st