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

简介: python中的__init__()方法 VS __new__()方法

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.使用元类metaclass


3.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

[2] https://www.cnblogs.com/zhouzhishuai/p/11410986.html

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

相关文章
|
1天前
|
人工智能 Python
【Python实用技能】建议收藏:自动化实现网页内容转PDF并保存的方法探索(含代码,亲测可用)
【Python实用技能】建议收藏:自动化实现网页内容转PDF并保存的方法探索(含代码,亲测可用)
18 0
|
6天前
|
存储 关系型数据库 MySQL
Python搭建代理IP池实现存储IP的方法
Python搭建代理IP池实现存储IP的方法
|
6天前
|
Python
Python动态IP代理防止被封的方法
Python动态IP代理防止被封的方法
|
6天前
|
数据采集 存储 安全
python检测代理ip是否可用的方法
python检测代理ip是否可用的方法
|
8天前
|
数据可视化 测试技术 Python
在Python和R中使用交叉验证方法提高模型性能
在Python和R中使用交叉验证方法提高模型性能
20 0
|
8天前
|
存储 监控 开发工具
对象存储OSS产品常见问题之python sdk中的append_object方法支持追加上传xls文件如何解决
对象存储OSS是基于互联网的数据存储服务模式,让用户可以安全、可靠地存储大量非结构化数据,如图片、音频、视频、文档等任意类型文件,并通过简单的基于HTTP/HTTPS协议的RESTful API接口进行访问和管理。本帖梳理了用户在实际使用中可能遇到的各种常见问题,涵盖了基础操作、性能优化、安全设置、费用管理、数据备份与恢复、跨区域同步、API接口调用等多个方面。
38 9
|
8天前
|
Python
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
51 0
|
14天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
14天前
|
程序员 开发者 Python
Python网络编程基础(Socket编程) 错误处理和异常处理的最佳实践
【4月更文挑战第11天】在网络编程中,错误处理和异常管理不仅是为了程序的健壮性,也是为了提供清晰的用户反馈以及优雅的故障恢复。在前面的章节中,我们讨论了如何使用`try-except`语句来处理网络错误。现在,我们将深入探讨错误处理和异常处理的最佳实践。
|
18天前
|
缓存 监控 Python
解密Python中的装饰器:优雅而强大的编程利器
Python中的装饰器是一种强大而又优雅的编程工具,它能够在不改变原有代码结构的情况下,为函数或类添加新的功能和行为。本文将深入解析Python装饰器的原理、用法和实际应用,帮助读者更好地理解和利用这一技术,提升代码的可维护性和可扩展性。

热门文章

最新文章