在类之外创建对象时如何留出内存?

时间:2019-04-17 09:07:38

标签: python python-3.x python-2.7

我读到__init__并没有创建对象(预留了内存)。

我找不到实际创建对象的人。 该对象创建在内部如何发生?

3 个答案:

答案 0 :(得分:2)

当您在Python中键入类似MyClass()的内容时,Python运行时将在__new__上调用MyClass,这应该构造一个对象;然后在新构造的对象上调用__init__。因此,__new__被称为“构造函数”,__init__被称为“初始化程序”。此序列在Python外部进行编码(对于CPython,使用C语言编写)。请访问Python文档,以详细了解__new____init__

答案 1 :(得分:2)

您可能正在寻找__new__

从Python的角度来看,假设您有一个直接继承自A的类object,那么发生的事情类似于以下内容:

  • A.__new__方法被调用
  • object.__new__被呼叫,cls=A
  • 调用
  • A.__init__方法,并使用从您的A.__new__转发的参数

示例:

class A():

    def __new__(cls, *args, **kwargs):
        print(f'__new__ called with args {args} and kwargs {kwargs}')
        return super().__new__(cls)  # object.__new__

    def __init__(self, *args, **kwargs):
        print(f'__init__ called with args {args} and kwargs {kwargs}')
        # args are discarded
        for key, arg in kwargs.items():
            setattr(self, key, arg)

a_instance = A('arg', kwarg=1)
a_instance.kwarg

输出:

__new__ called with args ('arg',) and kwargs {'kwarg': 1}
__init__ called with args ('arg',) and kwargs {'kwarg': 1}
1

通常,__new__不需要做任何事情,因为因为Python对象通常是可变的,所以在初始化实例属性和修改实例属性之间没有区别。

>

根据我的经验,覆盖__new__的主要用例是从不可变类型(例如tuple)继承。在这种情况下,您必须在创建时初始化所有实例属性,因此__init__为时已晚。

答案 2 :(得分:2)

简短答案

简而言之,创建对象的方法是__new__,而__init__只是初始化创建的对象。

长答案

但是,如果您想更深入地了解将要在python中创建对象的情况,请继续阅读。


在python 2.x中,python旧样式和新样式类中有两种类型的类。

class C: # A old-style class sample 
     pass

class C(object): # A old-style class sample 
     pass

在老式类中,没有__new__方法,因此__init__是构造函数。 但是,在python 3.x中,仅保留了新型类(与为类选择的定义无关,它将继承自基类“ Object”)。在新型类中,__new____init__方法均可用。 __new____init__分别是构造函数和初始值设定项,允许您覆盖它们两者(注意,在某些情况下,通常不需要覆盖__new__方法例如定义元类等,因此在不需要时不要对其进行操作。) 最后,当要创建对象时,构造函数将在初始化之前被调用。

class A(object):  # -> don't forget the object specified as base

def __new__(cls):
    print "A.__new__ called"
    return super(A, cls).__new__(cls)

def __init__(self):
    print "A.__init__ called"

A()

输出将是:

A.__new__ called
A.__init__ called