Luckylau's Blog

你懂python吗(8)

__init____new__的区别

__init____new__的主要区别如下:

  1. __new__是一个静态方法,而__init__是一个实例方法.
  2. __new__方法会返回一个创建的实例,而__init__什么都不返回.
  3. 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
  4. 当创建一个新实例时调用__new__,初始化一个实例时用__init__

__new__的使用

我们先看一下普通例子:

1
2
3
4
5
6
7
8
9
10
11
12
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return "<Person <%s %s>" %(self.name,self.age)
if __name__ == '__main__':
person=Person("luckylau",23)
print person
# output
<Person <luckylau 23>

这是__init__最普通的用法了。但__init__其实不是实例化一个类的时候第一个被调用 的方法。当使用 Persion(name, age) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 __new__ 方法,等价于以下过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person(object):
def __new__(cls, name,age):
print " __new__ called "
return super(Person,cls).__new__(cls,name,age)
def __init__(self,name,age):
print " __init__ called "
self.name=name
self.age=age
def __str__(self):
return "<Person <%s %s>" %(self.name,self.age)
if __name__ == '__main__':
person=Person("luckylau",23)
print person

1.person = Person(name, age)
2.首先执行使用name和age参数来执行Person类的__new__方法,这个__new__方法会 返回Person类的一个实例(通常情况下是使用 super(Persion, cls).__new__(cls, … …) 这样的方式),
3.然后利用这个类实例来调用类的__init__方法,上一步里面__new__产生的实例也就是 __init__里面的 self。
所以,__init____new__ 最主要的区别在于:
1.__init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。
2.__new__ 通常用于控制生成一个新实例的过程。它是类级别的方法。

因此一个应用就是__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。

1
2
3
4
5
6
7
8
9
10
class PositiveInteger(int):
def __new__(cls, value):
print " __new__ called "
return super(PositiveInteger,cls).__new__(cls,abs(value))
if __name__ == '__main__':
num=PositiveInteger(-123)
print num
#output
123
1
2
3
4
5
6
7
8
9
10
class PositiveInteger(int):
def __init__(cls, value):
print " __new__ called "
return super(PositiveInteger,cls).__init__(cls,abs(value))
if __name__ == '__main__':
num=PositiveInteger(-123)
print num
#output
-123

还有一个应用便是__new__来实现单例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person(object):
def __new__(cls,*args,**kwargs):
if not hasattr(cls,'instance'):
cls.instance=super(Person,cls).__new__(cls,*args,**kwargs)
return cls.instance
def __init__(self,name,age):
self.name=name
self.age=age
if __name__ == '__main__':
person=Person("lucky",23)
person2=Person("lau",24)
print id(person)
print id(person2)
#output
140094508307088
140094508307088
Luckylau wechat
如果对您有价值,看官可以打赏的!