在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__
本身还是在其元类中定义的方法?
答案 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章。