16. __new__ 和 __init__

16.1. 老式类与新式类

Python 2.x 中类的定义分为新式定义和老式定义两种。 老式类定义时默认是继承自 type ,而新式类在定义时显示地继承 object 类。

1class A: ## 老式类
2    pass
3
4class B(object): ## 新式类
5    pass
 1>>> print A.__bases__
 2()
 3>>> print dir(A)
 4['__doc__', '__module__']
 5
 6>>> print B.__bases__
 7(<type 'object'>,)
 8>>> print dir(B)
 9['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
10>>> print B.__class__
11<type 'type'>

Python 3.x 中没有新式类和老式类之分,它们都继承自 object 类,因此可以不用显示地指定其基类。

16.2. 老式类

老式类中其实并没有 __new__ 方法,因为 __init__ 就是它的构造方法(函数)。即使重写 __new__ 方法,也永远不会执行。

__init__ 只能返回 None

16.3. 新式类

16.3.1. 功能

新式类中,__new__ (构造函数)单独地 创建 一个对象,而 __init__ (初始化函数)负责 初始化 这个对象。

  • __new__ 至少要有一个参数 cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供。

  • __init__ 有一个参数 self,就是 __new__ 返回的实例,__init____new__ 的基础上可以完成一些其它初始化的动作,__init__ 不需要返回值(或者说返回 None )。

16.3.2. 返回值

__init__ 只能返回 None

__new__ 返回创建的实例对象并传递给 __init__self 参数。如果 __new__ 没有返回值,或者没有正确返回 当前类 cls 的实例,则 __init__ 不会被调用。

1class A(object):
2
3    def __new__(cls):
4        print "A.__new__ called"
5        print cls
6        return super(A, cls).__new__(cls)
7
8    def __init__(self):
9        print "A.__init__ called"
1>>> a = A()
2A.__new__ called
3<class '__main__.A'> ## cls
4A.__init__ called
5
6>>> a.__class__     ## type(a)
7<class '__main__.A'>
8>>> A.__class__
9<type 'type'>

__new__ 返回父类的对象:

 1class A(object):
 2    pass
 3
 4class B(A):
 5    def __new__(cls):
 6        print "B.__new__ called"
 7        return A() ## 或者写为: return super(B,cls).__new__(A)
 8
 9    def __init__(self):  ## 不会被调用
10        print "B.__init__ called"
1>>> b = B()
2B.__new__ called
3>>> print type(b)
4<class '__main__.A'>

16.3.3. __new__ 实现单例

单例(Singleton):类只有一个对象。None 就是一个单例,所有的变量只要是 None ,它一定和 None 指向同一个内存地址。

 1class Singleton(object):
 2    _instance = None
 3    def __new__(cls, *args, **kwargs):
 4        if cls._instance is None:
 5            cls._instance = super(Singleton, cls).__new__(cls)
 6
 7        return cls._instance
 8
 9    def __init__(self, *args, **kwargs):
10        pass
1>>> s1 = Singleton()
2>>> print id(s1)
3317973448
4>>> s2 = Singleton()
5>>> print id(s2)
6317973448
 1import threading
 2
 3class Singleton(object):
 4    _instance_lock = threading.Lock()
 5
 6    def __new__(cls, *args, **kwargs):
 7        if not hasattr(cls, '_instance'):
 8            with cls._instance_lock:  # 加锁,线程安全
 9                cls._instance = super(Singleton, cls).__new__(cls)
10        return cls._instance
11
12    def __init__(self, x):
13        self.x = x
14
15def task(arg):
16    obj = Singleton(arg)
17    print(obj)
18
19for _x in range(10):
20    t = threading.Thread(target=task, args=(_x,))
21    t.start()

16.4. 附:__repr__ 和 __str__

 1class Base(object):
 2    def __init__(self, name="fong"):
 3        self.name = name
 4
 5class A(Base):
 6    def __repr__(self):
 7        return "Class A(%s)" % self.name
 8
 9class B(Base):
10    def __str__(self):
11        return "Class B(%s)" % self.name
 1>>> a = A()
 2>>> a
 3Class A(fong)
 4>>> print a
 5Class A(fong)
 6
 7>>> b = B()
 8>>> b
 9<B object at 0x0000000012B7FB70>
10>>> print b
11Class B(fong)

16.5. 参考资料

  1. 深入理解Python中的 __new__ 和 __init__

  1. 详解Python中的 __init__ 和 __new__(静态方法)

  1. Python面试之理解 __new__ 和 __init__ 的区别

  1. Python中__repr__和__str__区别

  1. python 单例模式