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. 参考资料
深入理解Python中的 __new__ 和 __init__
详解Python中的 __init__ 和 __new__(静态方法)
Python面试之理解 __new__ 和 __init__ 的区别
Python中__repr__和__str__区别
python 单例模式