使用类包装器和 __new__ 装饰类

2024-01-08

Code:

import functools


class MyInt1(int):

    def __new__(cls, x, value):
        print("MyInt1.__new__", cls, x, value)
        return super().__new__(cls, x, base=2)

    def __init__(self, x, value):
        print("MyInt1.__init__", self, x, value)
        self.value = value
        super().__init__()


class MyInt2:

    def __init__(self, x, value):
        print("MyInt2.__init__", self, x, value)
        self.value = value


def decorator(class_):

    class Wrapper(class_):

        def __new__(cls, *args, **kwargs):
            print("Wrapper.__new__", cls, args, kwargs)
            obj = super().__new__(cls, *args, **kwargs)
            ...
            return obj

        def __init__(self, *args, **kwargs):
            print("Wrapper.__init__", self, args, kwargs)
            functools.update_wrapper(self, class_)
            super().__init__(*args, **kwargs)

    return Wrapper


c = decorator(MyInt1)("101", 42)
print(c, c.value)
c = decorator(MyInt2)("101", 42)
print(c, c.value)

Output:

Wrapper.__new__ <class '__main__.decorator.<locals>.Wrapper'> ('101', 42) {}
MyInt1.__new__ <class '__main__.decorator.<locals>.Wrapper'> 101 42
Wrapper.__init__ 5 ('101', 42) {}
MyInt1.__init__ 5 101 42
5 42
Wrapper.__new__ <class '__main__.decorator.<locals>.Wrapper'> ('101', 42) {}
Traceback (most recent call last):
  File "tmp2.py", line 42, in <module>
    c = decorator(MyInt2)("101", 42)
  File "tmp2.py", line 28, in __new__
    obj = super().__new__(cls, *args, **kwargs)
TypeError: object() takes no parameters
  • 如果我真的不知道传递给装饰器的类是什么,应该如何处理?
  • 为什么它不适用于常见模式?
  • 为什么默认__new__不接受__init__论点?

我发现的唯一方法是inspect.isbuiltin检查super().__new__和分支,但这很脏。


很难找到有关 Python 基类(对象)行为的详细信息,该行为是为了实际实现而实现的__init__创建新类时:

object's own __init__ and __new__除此之外,方法不带任何参数self and cls。然而,如果它们是从子类(恰好是 Python 中定义的所有其他类)调用的,这些方法的每个方法都会检查子类是否定义了其中一个而不是另一个(即对象的__init__检查正在实例化的类是否也已定义__new__或不)。

如果任一方法发现相反的方法已被覆盖而其本身没有被覆盖,它只会吞掉任何额外的参数:因此是一个用户的类__init__可以有参数,而不必担心相同的参数 - 将被传递给object.__new__会导致错误,

因此,您遇到的问题是,在此检查期间,例如,对象的__new__发现你的包装纸有__init__定义 - 因此它不会吞咽任何参数 - 和错误,因为有额外的参数。

如果您保留此模式,解决此问题的唯一方法是在装饰器中重新实现相同的逻辑:

def decorator(class_):

    def has_method(cls, meth):
        # (FIXME:the check bellow does not take in account other applications of this decorator)
        return any(meth in ancestor.__dict__ for ancestor in cls.__mro__[:-1]):

    def has_new(cls):
        return has_method(cls, "__new__")

    def has_init(cls):
        return has_method(cls, "__init__")

    class Wrapper(class_):

        def __new__(cls, *args, **kwargs):
            print("Wrapper.__new__", cls, args, kwargs)
            if  (args or kwargs) and not has_new(cls) and has_init(cls):
                args, kwargs = (), {}
            obj = super().__new__(cls, *args, **kwargs)
            ...
            return obj

        def __init__(self, *args, **kwargs):
            print("Wrapper.__init__", self, args, kwargs)
            functools.update_wrapper(self, class_)
            cls = self.__class__
            if (args or kwargs) and not has_init(cls) and has_new(cls):
                args, kwargs = (), {}
            super().__init__(*args, **kwargs)

    return Wrapper

https://mail.python.org/pipermail/python-list/2016-March/704027.html https://mail.python.org/pipermail/python-list/2016-March/704027.html是存在这种行为的暗示 - 我已经在官方文档中看到过它,但在某些地方我不记得是哪个。

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

使用类包装器和 __new__ 装饰类 的相关文章

随机推荐

  • Android动画中的pivotX和pivotY是什么意思? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 这两个术语出现在很多地方 但它们在 Android 动画上下文中到底意味着什么 枢轴X和枢轴Y是动画的中心点 例如 如果你想做放大动画 你
  • iOS 8 Swift Xcode 6 - 设置顶部导航栏背景颜色和高度

    我到处查看并测试了 Stack 上发布的所有代码片段 但没有任何东西对我有用 因为我需要它工作 我只是想设置 导航栏高度 导航栏背景颜色 RGB 导航栏居中徽标 我正在使用 iOS8 Xcode 6 和 Swift 非常感谢您的明确答复 这
  • Tmux:如何使用选择树过滤当前会话窗口并格式化输出以显示不带主机名的窗口名称

    我想配置tmux choose tree to 仅显示我当前会话的窗口 但与此同时我想保留我当前使用的格式 不带主机名的窗口名称 我当前的设置是 bind key w choose tree F window name 看起来像这样 我发现
  • 将删除导航栏边框转换为 swift

    我正在尝试快速删除导航栏边框 这是通过在 Objective C 中使用以下代码来完成的 UINavigationBar appearance setShadowImage UIImage alloc init UINavigationBa
  • 使用超类静态方法获取子类的实例

    我有一个超类 我想转发一个名为的静态方法getInstance 到所有子类 创建子类的实例时 我然后在超类中注册该实例 可能使用哈希表 其中键基于getClass 然后 我希望使用前面提到的静态方法 getInstance 其中超类方法将返
  • PHP 中使用特殊字符对数组进行排序

    我有一个包含西班牙语语言名称的数组 lang ko coreano korean lang ar rabe arabic lang es espa ol spanish lang fr franc s french 我需要对数组进行排序并维
  • 跳过配置文件“main/binary-i386/Packages”的获取

    下午好 请告诉我我做错了什么 我刚在电脑上安装了Linux Ubuntu 但仍然对它一无所知 我尝试安装 PostreSQL 和 pgAdmin 我按照这个视频教程安装的https www youtube com watch v Vdzb7
  • Perl:打印传递给子例程的数组名称

    我将一个数组和一个标量传递给一个函数 以检查该值是否属于数组的一部分 如果它不是数组的一部分 则将其推送到数组 出于参考目的 它必须显示的是在推动它时必须显示数组的名称 这是我的代码 use v5 10 1 use strict use w
  • Angular2 Rxjs 404错误

    尝试启动 Angular2 应用程序时出现以下错误 Failed to load resource the server responded with a status of 404 Not Found angular2 polyfills
  • 文件写入在程序流程中应该发生时却没有发生

    这对我来说不是一个新问题 从 C 到 PERL 再到 Windows Mobile Windows XP 和其他 Windows 版本上的 Python 这个问题一直存在 让我心烦意乱 现在 在我最新的脚本中 这种情况再次发生 更具体地说
  • 使用 Expo 时如何忽略 fetch() 调用中的 SSL 证书问题?

    似乎反应原生无法在 fetch 调用期间禁用 SSL 验证 有人提到here https stackoverflow com questions 51130878 how to disable ssl check in react nati
  • 使用小数分隔符和可选的千位分隔符匹配数字的正则表达式

    我需要使用小数分隔符和千位分隔符 可选 来验证数字是否有效 我需要一个正则表达式 因为当前的代码不是由我完成的 使用的正则表达式无法正常工作 我的目标是修复它 因此以下组合是合法的 使用 作为小数点分隔符和 作为千位分隔符 10000 10
  • 如何在 Spring DM 中获取 BundleContext?

    我刚刚接触 Spring DM 我想访问 Bundlecontext 我的问题是我有一个包含 Activator 的捆绑包 但它没有 xml 配置文件 我无法触及这个捆绑包 那么我需要访问 BundleContext 和 serviceRe
  • CSS/Flexbox:仅显示容器中容纳的尽可能多的项目

    我的目标是构建一个面包屑样式组件 其中 显示项目的水平列表 每个项目都有最大宽度 如果宽度不足以显示项目 则从列表开头省略项目 优先考虑last列表中的项目 所有布局仅通过 CSS 实现 没有 JS 调整大小观察器等 Flexbox 似乎是
  • 如何检查Selenium WebDriver下载的文件?

    我使用 C 在 Selenium webdriver 中编写了一个自动化测试 其中一个步骤需要从服务器下载 XLSX 文件 如何验证文件是否已成功下载并获取其名称 Regards 我通过以下源代码找到了解决方案 string current
  • 包含服务器上任何位置的文件

    我的网站在生产服务器上完美运行 我已将其移至另一个网络服务器 VPS 让我用例子来解释一下 目录结构 includes header php business index php some other files index2 php 在我
  • 插入python数组以最小化元素之间的最大差异

    插值一维数组以使元素之间的最大差异最小化的简洁且可读的方法是什么 例如 如果我有数组 4 9 13 25 并且允许我再添加 1 个数字以最小化元素之间的最大差异 我会在 13 和 25 之间插入 19 最大差异现在是 6 而不是 12 当然
  • 在 MVC 中使用 ASP.NET 服务器控件?

    在我当前的项目中 我需要添加一项功能 允许用户查看其上传的 PDF 的缩略图 我找到了一个方便的组件 http www tallcomponents com pdfthumbnail aspx就实现了这一点 基本版本是免费的 但足以满足我当
  • 为什么原始类型有一个“类”,它是如何使用的?

    谈论 Java 7 您可以获得一个基本类型的类 如下所示 Class classOfInt int class 对于每一个 您都会得到一个名为原始类型的 类 int class gt int byte class gt byte doubl
  • 使用类包装器和 __new__ 装饰类

    Code import functools class MyInt1 int def new cls x value print MyInt1 new cls x value return super new cls x base 2 de