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

为什么在一个类中都定义了“ __new__”和“ __init__”

邵赞
2023-03-14
问题内容

我认为您可以在类中定义“ __init__”或“
__new__”,但是为什么都在django.utils.datastructures.py中定义。

我的代码

class a(object):
    def __init__(self):
        print  'aaa'
    def __new__(self):
        print 'sss'

a()#print 'sss'

class b:
    def __init__(self):
        print  'aaa'
    def __new__(self):
        print 'sss'
b()#print 'aaa'

datastructures.py:

class SortedDict(dict):
    """
    A dictionary that keeps its keys in the order in which they're inserted.
    """
    def __new__(cls, *args, **kwargs):
        instance = super(SortedDict, cls).__new__(cls, *args, **kwargs)
        instance.keyOrder = []
        return instance

    def __init__(self, data=None):
        if data is None:
            data = {}
        super(SortedDict, self).__init__(data)
        if isinstance(data, dict):
            self.keyOrder = data.keys()
        else:
            self.keyOrder = []
            for key, value in data:
                if key not in self.keyOrder:
                    self.keyOrder.append(key)

以及SortedDict.__init__将在什么情况下致电。

谢谢


问题答案:

您可以定义一个或两个的__new____init__

__new__必须返回一个对象-
可以是一个新对象(通常将任务委派给该对象type.__new__),一个现有对象(以实现单例,从池中“回收”实例,依此类推),甚至可以 不是
一个实例。班级。如果__new__返回该类的实例(新的或现有的),__init__则对其进行调用;如果__new__返回一个对象,这
不是 一个类的实例,则__init__ 叫。

__init__将类实例作为其第一项传递给它(以相同的状态__new__返回,即通常为“空”),并且必须根据需要对其进行更改以使其可以使用(通常是通过添加属性)。

总的来说,最好将其__init__用于所有可以做的事情-
并且__new__,如果遗留了一些__init__不能做的事情,则应使用该“多余的东西”。

因此,您通常会定义两者是否可以在其中做些有用的事情__init__,而不是定义实例化类时想要发生的一切。

例如,考虑一个既有子类int又具有foo插槽的类,并且您希望使用的初始化器int和的初始化器实例化该类.foo。由于这int是不可变的,因此该部分必须在中发生__new__,因此,一个人可以编写以下代码:

>>> class x(int):
...   def __new__(cls, i, foo):
...     self = int.__new__(cls, i)
...     return self
...   def __init__(self, i, foo):
...     self.foo = foo
...   __slots__ = 'foo',
... 
>>> a = x(23, 'bah')
>>> print a
23
>>> print a.foo
bah
>>>

在实践中,这种简单的情况下,没有人会如果你失去了头脑__init__,只是移动self.foo = foo__new__。但是,如果初始化足够丰富且复杂,以至于无法最佳使用__init__,则此想法值得牢记。



 类似资料:
  • 问题内容: 为什么glibc和pthread库都定义了相同的API?这是快照 问题答案: 也是glibc的一部分,它们都包含某些符号的 (相同) 定义。 如果您要查找,则会发现它仅存在于-这意味着程序必须链接到实际创建的线程 ,但是可以在仅链接到的单线程程序中使用互斥体和条件变量 。这对于共享内存中存在的进程间互斥锁和进程间条件变量很有用,并用于与单独的进程进行同步 。(由于下面的Zan Lynx

  • 问题内容: 似乎应该已经问过这个问题,但是搜索没有发现任何问题。 我一直想知道让我们将所有代码放入类或接口的意义何在。我似乎记得,要求像C这样的函数有一些优点,但对于类却没有。像Python这样的语言在某种程度上比Java更面向对象,因为它们没有基元,但是您可以将代码放在任何需要的地方。 这是对OOP的某种“误解”吗?毕竟,您可以像在C语言中一样编写过程代码,并将其放在类中,但是不会面向对象。 问

  • 如果你想定义一个类,你只需要使用class关键字。 class MainActivity{ } 它有一个默认唯一的构造器。我们会在以后的课程中学习在特殊的情况下创建其它额外的构造器,但是请记住大部分情况下你只需要这个默认的构造器。你只需要在类名后面写上它的参数。如果这个类没有任何内容可以省略大括号: class Person(name: String, surname: String) 那么构造函

  • 我写了一些代码来解决下面的问题。我有trid一些测试用例,它们都通过了,但当我提交我的答案自动标记时,结果是失败。我不知道问题出在哪里。 下面是问题和相应的链接: 下面是我的代码(在提交给系统之前,它需要替换类名为Main): 下面的C++代码是正确的,并且总是通过

  • 问题内容: 为什么B类无法公开?如何在其他班级使用班级?在Cons中定义它更好吗? 问题答案: 根据Java语言规范,文件(.java)中只能有一个公共类,并且文件名应与公共类名相同。 如果希望在其他地方访问B类,则可以创建一个单独的B.java文件,然后将B类代码移至该文件。 该线程可以为您提供更多信息。

  • 以下是输出信息: 线程“main”java.lang.noClassDeffounder:top/example/study/testclass(名称错误:top/example/study/testclass)在java.base/java.lang.classloader.defineclass1(本机方法)在java.base/java.lang.classloader.defineclas