旧式和新式类中的
__NEW__
和__INIT__
本文的目的是讨论Python的__new__
和__init__
方法。
该new和init方法不同的行为本身之间以及旧式与新式python类定义之间。
了解__new__
和__init__
之间的区别
这两种方法的主要区别是__new__
处理对象创建,而__init__
处理对象初始化。
在实例化过程中,如果定义不同,这两者在工作方式上略有差异。
有关Python中的类
Classes in python are classified as new-style and old-style. Old-style classes are the ones that are prior to python 3 and defined without inheriting from base class 'object', which in turn is inherited from 'type' by default.
python 2.x中的旧式类:
class A: # -> inherits from 'type'
pass
python 2.x中的新式类:
class A(object): # -> clearly inherits from 'object'
pass
In python 3 there aren't new or old styles of classes and they inherit directly from 'object' so there is no need to specify it as a base anymore.
在本文的其余部分中,我们将介绍两种情况下的 __new__
和__init__
方法,以确定它们的行为方式以及如何使用它们。
深度讲解
Before diving into the actual implementations you need to know that new accepts cls as it's first parameter and init accepts self, because when calling new you actually don't have an instance yet, therefore no self exists at that moment, whereas init is called after new and the instance is in place, so you can use self with it.
__new__
和__init__
用于旧式类
旧式类实际上并没有__new__
方法,因为对于它们来说__init__
是构造函数,假设如下:
class A:
def __new__(cls):
print "A.__new__ is called" # -> this is never called
A()
在这种情况下new 的主体将永远不会被执行,因为它不是老式类的目的。
如果我们要重写__init__
:
class A:
def __init__(self):
print "A.__init__ called"
A()
输出将是:
A.__init__ called
现在让我们尝试从__init__
返回一些东西:
class A:
def __init__(self):
return 29
A()
这会产生:
TypeError: __init__() should return None
所以这意味着我们实际上无法控制实例化旧式类时要返回的内容。
__new__
和__init__
用于新的样式类
新风格的类让开发人员同时覆盖__new__
和__init__
,他们有不同的用途,__new__
(构造函数)仅用于创建object
和__init__
(初始化程序)来初始化它。
让我们看看他们的执行顺序:
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
您可能想知道__init__
或__new__
在哪里被调用,而我为您准备的是__new__
在调用类名(实例化时)时自动调用,而__init__
在__new__
每次由__new__
返回时被调用,而将实例返回传递给__init__
且self'
作为参数,因此,即使您将该实例保存在全局/静态的某个位置,并且每次先都从__new__
返回,每次都会调用__init__
。
知道了这一点就意味着如果我们调用
super
的__new__
,那么__init__
将不会被执行。让我们来看看是不是这样的情况:
class A(object):
def __new__(cls):
print "A.__new__ called"
def __init__(self):
print "A.__init__ called" # -> is actually never called
print A()
输出是:
A.__new__ called
None
显然,实例被识别为None
,因为我们不从构造函数返回任何东西。
想知道如果我们从__new__
返回什么可能会发生什么?
猜猜输出是什么:
class A(object):
def __new__(cls):
print "A.__new__ called"
return 29
print A()
让我们看看当我们从__init__
返回时会发生什么:
A.__new__ called
29
这产生:
class A(object):
def __init__(self):
print "A.__init__ called"
return 33 # -> TypeError: __init__ should return None
A()
这主要是因为调用__init__
的处理程序 引发了TypeError
异常,并且从__init__
返回任何内容都没有意义,因为它的目的只是改变新创建的实例的新状态。
看起来新型的类在灵活性方面有提高,允许我们在创建和初始化级别执行任何PRE / POST
操作,并使我们控制在实例化时返回的内容。
考虑到这一点,我们试着返回一个不同类的实例。
首先我们定义一个类:
class Sample(object):
def __str__(self):
return "SAMPLE"
然后我们定义__new__
覆盖类:
class A(object):
def __new__(cls):
return Sample()
这也可以写成:
class A(object):
def __new__(cls):
return super(A, cls).__new__(Sample)
然后调用:
print A()
那会输出:
SAMPLE
这里是我写的一个例子,帮助大家理解:
class Alfa(object):
def __new__(cls):
#creat a generate ,get int value by filter
#g=(x for x in range(10) if isinstance(x,int) and x <0)
print("__new__")
#return an parent instance
return super().__new__(cls)
def __init__(self):
print ("__init__")
print (id(self))#print self address at Memory
super().__init__()
#l=['a',1,2,-2,-5,8,9,0]
t=Alfa()# instantiation a object
print(id(t))#print self address at Memory
print(t)