1. new 和__init__方法的区别:
先看一个例子:
# -*- coding: utf-8 -*-
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__':
name = Person('xxx', 24)
print name
当实例化的时候,结果:
__new__ called.
__init__ called.
<Person: xxx(24)>
通过运行这段代码,我们可以看到,new方法的调用是发生在init之前的。其实当 你实例化一个类的时候,具体的执行逻辑是这样的:
1.p = 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 通常用于控制生成一个新实例的过程。它是类级别的方法。
3、new至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
4、new必须要有返回值,返回实例化出来的实例,这点在自己实现new时要特别注意,可以return父类new出来的实例,或者直接是object的new出来的实例
5、可以将类比作制造商,new方法就是前期的原材料购买环节,init方法就是在有原材料的基础上,加工,初始化商品环节
2. 什么时候需要__new__
new方法主要是当你继承一些不可变的class
时(比如int, str, tuple
), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass
。
具体我们可以用int
来作为一个例子:
假如我们需要一个永远都是正数的整数类型:
class PositiveInteger(int):
def __init__(self, value):
super(PositiveInteger, self).__init__(self, abs(value))
i = PositiveInteger(-3)
print i
但运行后会发现,结果根本不是我们想的那样,我们任然得到了-3。这是因为对于int
这种 不可变的对象,我们只有重载它的new方法才能起到自定义的作用
修改后的代码:
class PositiveInteger(int):
def __new__(cls, value):
return super(PositiveInteger, cls).__new__(cls, abs(value))
i = PositiveInteger(-3)
print i
通过重载new方法,我们实现了需要的功能。
3. 单例模式
-
单例是什么
举个常见的单例模式例子,我们日常使用的电脑上都有一个回收站,在整个操作系统中,回收站只能有一个实例,整个系统都使用这个唯一的实例,而且回收站自行提供自己的实例。因此回收站是单例模式的应用。
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。 -
创建单例-保证只有1个对象
实例化一个单例
class Singleton(object):
__instance = None
def __new__(cls, age, name):
#如果类数字__instance没有或者没有赋值
#那么就创建一个对象,并且赋值为这个对象的引用,保证下次调用这个方法时
#能够知道之前已经创建过对象了,这样就保证了只有1个对象
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
a = Singleton(18, "xxx")
b = Singleton(8, "xxx")
print(id(a))
print(id(b))
a.age = 19 #给a指向的对象添加一个属性
print(b.age)#获取b指向的对象的age属性
运行结果:
4391023224
4391023224
19
- 创建单例时,只执行1次
init
方法
实例化一个单例
class Singleton(object):
__instance = None
__first_init = False
def __new__(cls, age, name):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self, age, name):
if not self.__first_init:
self.age = age
self.name = name
Singleton.__first_init = True
a = Singleton(18, "xxx")
b = Singleton(8, "xxx")
print(id(a))
print(id(b))
print(a.age)
print(b.age)
a.age = 19
print(b.age)
运行结果:
139953926130600
139953926130600
18
18
19
转载
链接:https://www.jianshu.com/p/6ca1b0cdef3b
链接:https://www.jianshu.com/p/08d7956601de