当前位置: 首页 > 面试题库 >

为什么object .__ new__在这三种情况下工作不同

薛博艺
2023-03-14
问题内容

来自问题的原因,或者说更确切地说,object .__new__在这两种情况下的工作方式不同

作者对为什么不感兴趣,而对如何感兴趣。

我非常想了解原因,尤其是:

  1. 为什么不object.__init__打印任何参数而不是object.__new__ (in testclass1)

  2. 为什么没有为testclass3引发错误?(因为除了自我之外没有其他参数)

>>> class testclass1(object):
    ...     pass
    ...

>>> class testclass2(object):
    ...     def __init__(self,param):
    ...             pass
    ...

>>> a = object.__new__(testclass1, 56)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: object.__new__() takes no parameters

>>> b = object.__new__(testclass2, 56)

>>> b
    <__main__.testclass2 object at 0x276a5d0>

>>> class testclass3(object):
    ...     def __init__(self):
    ...             pass
    ...

>>> c = object.__new__(testclass3, 56)

>>> c
    <__main__.testclass3 object at 0x276a790>

>>> c1 = object.__new__(testclass3)

>>> c1
    <__main__.testclass3 object at 0x276a810>

问题答案:

您正在使用旧的Python版本;此错误消息已更新:

>>> object.__new__(testclass1, 56)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object() takes no parameters

Python只会抱怨__init__既不支持__new__又不__init__被覆盖的参数。例如,当您同时继承时objecttestclass1适合这种情况,testclass3不是因为它有一个__init__方法。

这是为了支持实现不使用的不可变类型__init__object在这种情况下将继承自该类型) 可变类型,
可变类型__new__则不必在乎参数的__init__期望值(通常是 更多的 参数)。

参见问题1683368,其中Guido van Rossum解释了他的动机。

typeobject.c源代码,有这样一段话:

您可能想知道为什么object.__new__()只有
object.__init__()不被覆盖时才抱怨参数,反之亦然。

考虑用例:

  1. 当两个都不被覆盖时,我们希望听到对过多(即任何)参数的抱怨,因为它们的存在可能表明存在错误。

  2. 定义不可变类型时,我们可能仅覆盖
    __new__(),因为__init__()调用时太晚了,无法初始化不可变对象。由于__new__()定义了类型的签名,因此不得不重写__init__()以阻止它抱怨过多的参数将是一件痛苦的事情。

  3. 定义Mutable类型时,我们可能仅覆盖
    __init__()。因此,这里有相反的推理:我们不想__new__()为了阻止抱怨而不必重写。

  4. __init__()被覆盖并且子类__init__()调用时
    object.__init__(),后者应该抱怨过多的参数;同上__new__()

用例2和3使得无条件检查多余的参数变得没有吸引力。解决所有四个用例的最佳解决方案如下:__init__()抱怨过多的参数,除非__new__()被覆盖__init__()且未被覆盖(IOW,如果__init__()被覆盖或__new__()未被覆盖);对称地,__new__()抱怨多余的参数,除非
__init__()被覆盖__new__()且未被覆盖(IOW,如果__new__()被覆盖或__init__()未被覆盖)。

但是,为了向后兼容,这会破坏太多的代码。因此,在2.6中,当两种方法都被覆盖时,我们将 警告 过多的参数。对于所有其他情况,我们将使用上述规则。

请注意,该.__init__()方法 本身
仍会抱怨!创建实例时,__new____init__都被调用;你的代码仅调用__new__直接和它 不会
调用__init__!创建的实例testclass1testclass3如果加上参数都失败:

>>> testclass1(56)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object() takes no parameters
>>> testclass3(56)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 1 argument (2 given)

唯一的区别在于,testclass1这是该object()抱怨的默认方法,而不是自定义的特定错误__init__



 类似资料:
  • 我有一个h2作为唯一的项目在一个容器div。我在容器上使用position:relative和h2上使用position:absolute/bottom:0使它与容器底部对齐。但是,我无法使h2文本与容器div的右侧对齐。 HTML: CSS: 链接:http://www.distributionaccess.com/new/stempath/about.html 我在h2上尝试了display:

  • 输入是:1。硬币中一定数量货币的总重量,2。旧货币硬币的价值和相应重量。 目标是找到给定金额货币的最低可能货币价值。 我的方法是按货币的价值/重量比升序对硬币进行排序,然后贪婪地将第一枚硬币的重量尽可能多地匹配到总和中(跟踪它匹配的次数),然后匹配将第二枚硬币的重量尽可能多次地放入余数中,等等,对于所有硬币或直到余数为零(如果不是,情况是不可能的)。 法官说我的答案是错误的。你能给我一个关于算法错

  • 问题内容: 我有PK,它是自增密钥。我需要将记录插入数据库中,然后取回该PK并在另一个插入中使用它。 但是,我想在一次交易中做到这一点。那可能吗。这样的想法是,如果我必须执行的任何更新/插入都失败了,那么我可以回滚所有内容,但是我的印象是我需要进行一次提交。 我本来打算先在ado.net上执行此操作,然后切换到存储过程,因为我认为这可能会解决此问题。 SP在这种情况下会帮助我吗? 问题答案: 是的

  • 事件处理程序添加到GameGui.java类的GridPane中,从第82行开始。 基本上,我试图找到您在网格窗格中拖动这个对象的任何节点的索引。通过将SetonMouseEnter应用到gridpane中的每个节点,我可以在不拖动的情况下完成这一任务,但是当我试图利用SetonMouseDragEnter时,我什么也没有得到。 有人有办法让这个工作吗? 这些是我应用于GridPane中节点的事件

  • 根据Java教程 将包装类型(整数)的对象转换为其相应的基元(int)值称为取消装箱。当包装类的对象为: 作为参数传递给需要相应基元类型的值的方法 分配给相应基元类型的变量 为什么在这种情况下会发生拆箱? 在这种情况下,这些事情发生在哪里?是否有管理数组中元素访问的底层方法?或者[]暗示某种变量?

  • 问题内容: 我编写了以下代码来实现Singleton模式: 当我编译此文件时,它应该生成Test.class和Test $ TestHolder.class,但它还会生成Test $ 1.class。这没有道理。那么,为什么以及如何呢? 问题答案: 类需要在中调用私有构造函数。但是它是私有的,实际上不能从另一个类中调用。因此,编译器发挥了作用。它 添加了一个仅知道的新的非私有构造函数!_该构造函数