python __new__方法有什么用_python中__init__()方法和__new__()方法的区别

__new__()是新式类中才出现的方法,即只有从object继承的类才有该方法。注意,新式类是从python2.2开始加入的,在python2.x中同时存在新式类和旧式类(旧式类也称经典类,主要是为了兼容以前的代码),但是在python3.x中已经完全摒弃旧式类了,在python3.x中即使不显示的写明从object继承,系统也会默认从object继承。

在旧式类中,实例的构造只调用__init__()这一个函数(至少从外表来看是如此),因此很多场合称__init__()为构造函数,在旧式类中这完全没问题,但是在新式类中这么叫并不完全合适。

在新式类中,实例的构造先调用__new__()函数返回一个实例,然后调用__init__()对返回的实例进行初始化。因此可以看出__new__()才是真正的构造函数,__init__()只是起到了初始化的过程。

1:__new__()与__init__()的调用顺序

#!/usr/bin/env python

class A(object):

def__init__(self,*args,**kwargs):

print "init &&&& %s" % self.__class__

def__new__(cls,*args,**kwargs):

print "new &&&& %s" % cls

return object.__new__(cls,*args,**kwargs)

a=A()

输出结果为:

new &&&&

init &&&&

如果把最后一行的return代码屏蔽掉,输出结果为:

new &&&&1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

一般来说,”init”和”new”函数都会有下面的形式:def __init__(self, *args, **kwargs):

# func_suite

def __new__(cls, *args, **kwargs):

# func_suite1

2

3

4

5

对于”new”和”init”可以概括为: “new”方法在Python中是真正的构造方法(创建并返回实例),通过这个方法可以产生一个”cls”对应的实例对象,所以说”new”方法一定要有返回。 对于”init”方法,是一个初始化的方法,”self”代表由类产生出来的实例对象,”init”将对这个对象进行相应的初始化操作。

重写_new_ 如果(新式)类中没有重写”new”方法,Python默认是调用该类的直接父类的”new”方法来构造该类的实例,如果该类的父类也没有重写”new”,那么将一直按照同样的规则追溯至object的”new”方法,因为object是所有新式类的基类。

而如果新式类中重写了”new”方法,那么可以选择任意一个其他的新式类(必须是新式类,只有新式类有”new”,因为所有新式类都是从object派生)的”new”方法来创建实例,包括这个新式类的所有前代类和后代类,只要它们不会造成递归死循环。

看一段例子代码:#!/usr/bin/env python

#coding:utf-8

class Foo(object):

def__new__(cls,*args,**kwargs):

obj = object.__new__(cls,*args,**kwargs)

#这里的object.__new__(cls,*args,**kwargs)等价于

# super(Foo,cls).__new__(cls,*args,**kwargs)

# object.__new__(Foo,*args,**kwargs)

# Bar.__new__(cls,*args,**kwargs)

# Student.__new__(cls,*args,**kwargs),即使Student和

# Foo没有关系也是允许的,因为Student是由object派生的新类

# 在任何新式类中,不能调用自身的__new__来创建实例,因为这会

# 造成死循环,所以要避免出现这样的语法 Foo.__new__(cls,*args,**kwargs)

# 或者 cls.__new__(cls,*args,**kwargs)

print "Calling __new__ for %s" % obj.__class__

return obj

class Bar(Foo):

def__new__(cls,*args,**kwargs):

obj = object.__new__(cls,*args,**kwargs)

print "Calling __new__ for %s" % obj.__class__

return obj

class Student(object):

#Student没有__new__方法,那么会自动调用父类的__new__方法来

#创建实例,即会自动调用object.__new__(cls)

pass

class Car(object):

def__new__(cls,*args,**kwargs):

obj = object.__new__(Bar,*args,**kwargs)

print "Calling __new__ for %s" % obj.__class__

return obj

foo = Foo()

bar = Bar()

car = Car()

运行结果是:

Calling __new__ for

Calling __new__ for

Calling __new__ for 1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

_init_的调用

“new”决定是否要使用该类的”init”方法,因为”new” 可以调用其他类的构造方法或者直接返回别的类创建的对象来作为本类的实例。 通常来说,新式类开始实例化时,”new”方法会返回cls(cls指代当前类)的实例,然后调用该类的”init”方法作为初始化方法,该方法接收这个实例(即self)作为自己的第一个参数,然后依次传入”new”方法中接收的位置参数和命名参数。 但是,如果”new”没有返回cls(即当前类)的实例,那么当前类的”init”方法是不会被调用的。看下面的例子:#!/usr/bin/env python

class A(object):

def __init__(self,*args,**kwargs):

print "calling __init__ from %s" % self.__class__

def __new__(cls,*args,**kwargs):

obj = object.__new__(cls,*args,**kwargs)

print "calling __new__ from %s" % obj.__class__

return obj

class B(A):

def __init__(self,*args,**kwargs):

print "calling __init__ from %s" % self.__class__

def __new__(cls,*args,**kwargs):

obj = object.__new__(A,*args,**kwargs)

print "calling __new__ from %s" % obj.__class__

return obj

b=B()

print type(b)1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

代码中,在B的”new”方法中,通过”obj = object.new(A, *args, **kwargs)”创建了一个A的实例,在这种情况下,B的”init”函数就不会被调用到。

运行结果是:calling __new__ from

1

2

派生不可变类型

关于”new”方法还有一个重要的用途就是用来派生不可变类型 例如,python中的float类型是一个不可变类型,如果想要从float中派生出一个子类,就可以使用”new”方法:#!/usr/bin/env python

class Round2Float(float):

def __new__(cls,num):

num = round(num,2)

obj = float.__new__(Round2Float,num)

return obj

f=Round2Float(4.324599)

print f1

2

3

4

5

6

7

8

9

10

这段程序从float类中派生出了一个Round2Float类,这个类的作用就是保留小数点后两位的浮点数。


版权声明:本文为weixin_39821874原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。