python中的__init__()方法 VS __new__()方法_Python


1.__init__()方法

__init__()方法是python中一个特殊的方法,它在初始化一个类的实例化对象时候调用。__init__()至少有一个参数self,它就是__new__()方法返回的实例对象,__init__()在__new__()的基础上完成一些初始化的操作。__init__()不需要返回值。__init()__方法使用如下例所示:
 1# @Author  : Curry_Coder (1217096231@qq.com)
 2# @Link    : https://www.jianshu.com/u/4645adadefec
 3# @Version : $Id$
 4
 5# __init()__
 6
 7class Person:
 8    def __init__(self, name, age):
 9        self.name = name
10        self.age = age
11
12    def __str__(self):
13        return '<Person: {0},{1}>'.format(self.name, self.age)
14
15
16if __name__ == '__main__':
17    p = Person('CurryCoder', 20)
18    print(p)
注意:__init__()方法在实例化类对象的时候,并不是第一个被调用的方法。例如,当使用Person('CurryCoder',20)这样的语句创建Person类的对象p时,最先被调用的方法是__new__()方法。因为只有最先调用__new__()方法才能创建出类的实例p,接着才能调用__init()方法来初始化这个实例对象p。2.__new__()方法

__new__()方法接收的参数虽然和__init__()方法一样,但__init__()方法是在类实例对象创建之后调用(用它来初始化实例对象),而 __new__()方法则是创建这个类实例对象的方法,优先被调用。__new__()方法至少有一个参数cls代表当前类,此参数在实例化时,由Python解释器自动识别。__new__()必须有返回值,返回实例对象。__new()__方法使用如下例所示:

 1#!/usr/bin/env python
 2# -*- coding: utf-8 -*-
 3# @Date    : 2020-06-09 09:35:26
 4# @Author  : Curry_Coder (1217096231@qq.com)
 5# @Link    : https://www.jianshu.com/u/4645adadefec
 6# @Version : $Id$
 7
 8# __new()__
 9
10
11class Person:
12    def __new__(cls, *args, **kwargs):
13        print('优先调用__new__()方法创建出实例化对象')
14        _instance = super(Person, cls).__new__(cls, **kwargs)
15        return _instance
16
17    def __init__(self, name, age):
18        print('调用__init__()方法来初始化实例对象')
19        self.name = name
20        self.age = age
21
22    def __str__(self):
23        return '<Person: {0}, {1}>'.format(self.name, self.age)
24
25
26if __name__ == '__main__':
27    p = Person('Person', ('James', 27))
28    print(p)
3.单例模式Singleton单例模式:一种常见的软件设计模式,该模式的主要目的是确保某一个类只有一个实例对象存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。在Python中,我们可以用多种方法来实现单例模式:    a.使用模块    b.使用__new__()方法    c.使用装饰器    d.使用元类metaclass3.1 使用模块Python的模块就是天然的单例模式。因为模块在第一次导入时,会生成.pyc文件。当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象。如下例所示:
1from mysingleton import my_singleton
2
3my_singleton.foo()
3.2 使用__new__()方法为了使类只能实例化出一个对象,于是可以使用__new__()方法来控制实例的创建过程。如下例所示:
 1#!/usr/bin/env python
 2# -*- coding: utf-8 -*-
 3# @Date    : 2020-06-09 09:35:26
 4# @Author  : Curry_Coder (1217096231@qq.com)
 5# @Link    : https://www.jianshu.com/u/4645adadefec
 6# @Version : $Id$
 7
 8
 9class Singleton(object):
10    _instance = None  # 类变量
11
12    def __new__(cls, *args, **kw):
13        if not cls._instance:
14            cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)  # 将类的实例和一个类变量 _instance 关联起来
16        return cls._instance
17
18
19class MyClass(Singleton):
20    a = 1
21
22
23one = MyClass()
24two = MyClass()
25print(one is two)
26print(id(one), id(two))
3.3 使用装饰器

装饰器(decorator)可以动态地修改一个类或函数的功能。也可以使用装饰器来装饰某个类,使其只能生成一个实例。

 1from functools import wraps
 2
 3# 定义了一个装饰器 singleton,它返回了一个内部函数getinstance,该函数会判断某个类是否在字典instances 中,如果不存在,则会将cls作为 key,cls(*args, **kw) 作为 value存到instances中。否则,直接返回instances[cls]
 4
 5
 6def singleton(cls):
 7    instances = {}
 8
 9    @wraps(cls)
10    def getinstance(*args, **kwargs):
11        if cls not in instances:
12            instances[cls] = cls(*args, **kwargs)
13        return instances[cls]
14    return getinstance
15
16
17# 被装饰的函数
18@singleton
19class MyClass(object):
20    a = 1
3.4 使用元类metaclass元类(metaclass)可以控制类的创建过程,它主要做三件事:a.拦截类的创建b.修改类的定义c.返回修改后的类
 1class Singleton(type):
 2    _instances = {}
 3
 4    def __call__(cls, *args, **kwargs):
 5        if cls not in cls._instances:
 6            cls._instances[cls] = super(
 7                Singleton, cls).__call__(*args, **kwargs)
 8        return cls._instances[cls]
 9
10
11class MyClass(metaclass=Singleton):
12    pass
4.参考资料

[1] https://mlln.cn/2018/11/12/python3%E7%9A%84__new__%E5%92%8C__init__%E6%96%B9%E6%B3%95%E7%9A%84%E6%AF%94%E8%BE%83%E5%92%8C%E4%BD%BF%E7%94%A8/#undefined

[3] https://www.jianshu.com/p/6f0b6275d27c