类和对象上的__new__和__init__

时间:2019-01-28 03:49:52

标签: python python-3.x class inheritance

在Python 3中,定义子类时,为什么需要使用cls作为__new__的第一个参数,而不需要使用self作为{{ 1}}?

一个例子:

__init__

当我比较这些功能时,我变得更加困惑:

class MyClass(object):
    def __new__(cls, *args, **kwargs):
        return super(MyClass, cls).__new__(cls, *args, **kwargs) # with `cls`
    def __init__(self, *args, **kwargs):
        return super(MyClass, self).__init__(*args, **kwargs) # without `self`

那么,这些结果背后的>>> cls = object >>> self = cls() >>> cls.__new__ is self.__new__ True >>> cls.__init__ is self.__init__ False >>> self.__init__() >>> cls.__init__() Traceback (most recent call last): ... __new__有什么区别?哪些方法是绑定的,哪些是免费的?为什么您可以呼叫__init__但不能呼叫self.__init__()cls.__init__()是在cls.__init__本身还是在其元类中定义的方法?

3 个答案:

答案 0 :(得分:3)

您可能会丢失的图片的最大部分是,__new__是一种静态方法,special-cased是一个静态方法,即使您不使用@staticmethod装饰器也是如此。

通过super()调用方法时,super()执行与通常为该方法执行的相同类型的参数绑定(使用descriptor protocol)。对于__new__之类的静态方法,这意味着不会自动绑定任何参数,因此必须显式传递cls。对于像__init__这样的实例方法,这意味着self是自动绑定的,这就是为什么您不必将self传递给super().__init__的原因。

答案 1 :(得分:1)

__new__的主要目的是分配该类的新实例,而__init__的工作是建立现有实例。

根据文档:

  

__new__()是静态方法(特殊情况,因此您不必这样声明)

另一方面,

__init__是合适的实例方法。可以在同一实例上多次调用它。

这足以说明您的终端会话:

>>> cls = object
>>> self = cls()

您刚刚打过电话object.__call__

self = cls.__new__()
if isinstance(self, cls):
    cls.__init__(self)
return self

请注意,__new__的返回值不必是其所属类的实例,但是只有在__init__的情况下才被调用。就您而言,就是这样。

>>> cls.__new__ is self.__new__
True

__new__是静态方法,因此尝试将其绑定到实例没有任何作用:它保留为类方法。这与调用cls时必须显式传递super().__new__的原因相同:这是相同的自由函数,不受类或实例的约束。

 >>> cls.__init__ is self.__init__
 False

这些不仅不一样,而且它们的类型也不同。 cls.__init__是常规函数。 self.__init__是一个绑定方法,缺少第一个参数cls.__init__

>>> self.__init__()

这已经被调用了,但是对于object来说,这是一个空操作,您可以拨打任意次。请注意,第一个参数没有传入,因为它是绑定方法。

>>> cls.__init__()

这正在调用原始的__init__函数,该函数要求传入self参数。由于您不这样做,因此引发了该问题。尝试以下方法:

>>> cls.__init__(self)

答案 2 :(得分:0)

<script> $(document).ready(function () { $('#button1').click(function (e) { $.getJSON("getItem.php", function(result){ $.each(result, function(i, field){ $("#div1").empty(); $("#div1").append(JSON.stringify(result)); //alert(JSON.stringify(data)); }); }); }); }); </script> 代表类本身,而cls代表对象本身。这些只是约定。
self方法在创建对象之前被称为之前,实际上,__new__应该创建对象并返回它。因此,它需要一个 class 来创建对象。之后,调用__new__初始化对象,因此它需要该对象作为第一个参数。

例如:

__init__

class MyClass: def __new__(cls, *args, **kwargs): # cls == MyClass return super().__new__(cls, *args, **kwargs) # cls here is because __new__ is staticmethods so you have to pass the cls explicitly # You can't use cls() here because it will call this methods again and again # causing recusion error def __init__(self, *args, **kwargs): # Here self is the instance(or object) of MyClass # So you can initialize it by self.xxx self.xxx = 'xxx' 是静态方法,因此类和实例共享相同的__new__方法。 __new__是实例方法。如果要通过类调用它,则需要将实例作为第一个参数显式传递。

__init__

Python中的任何东西都是对象,包括类本身。因此,对于类,它具有自己的cls.__init__(self) __new____init__使用它们来创建类和初始化类。< br /> 这些是Python的元编程,我建议阅读Python Cookbook的第9章。

相关问题