Python每日一题:__new__ 与 __init__
时间:2022-07-23
本文章向大家介绍Python每日一题:__new__ 与 __init__,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目:Python 中__init__ 与 __new 的区别?
扩展:1.怎么理解 __new__?
2. Python 中怎么实现单例模式?
3. Python 中类的实例化是什么样的过程?
答案要点:
- __new__() 是一个静态方法,尽管并没有 @staticmethod 来修饰。它主要用于生成类的实例对象,所以当执行 a = A() 时,会首先执行 __new__()。这个方法是有返回值的,一般它的返回值是当前调用类的实例对象。它的定义如下:
# __new__ 的参数是 类,一旦这个方法创建过实例对象后就会调用 __init__()
object.__new__(cls[,...])
pass
# 如果需要调用父类的 __new__
python2
super(子类名, cls).__new__(cls[,...])
python3
super().__new__(cls[,...])
- __init__ 是在实例对象被创建之后才被调用的,也就是在执行完 __new__ 之后。它的定义如下:
# 实例方法都会以 self 开头,这个 self 其实就是当前的实例对象
# 实例对象当然是要先创建的,既然在调用 __init__ 参数就已经是 self 了,
# 说明在这之前一定是有方法去生成实例对象的
object.__init__(self[,...])
pass
# 如果需要调用父类的 __init__
python2
super(子类名, self).__init__([args...])
python3
super().__init__([args...])
- __init__ 返回值为 None,如果返回任意一个非 None 的值,会报 TypeError。示例如下:
class Test(object):
def __init__(self):
return "123"
t = Test() # TypeError: __init__() should return None, not 'str'
- __init__() 方法的作用很简单,和我们在 JAVA 中的构造方法是类似的,用来给实例属性赋值等操作。而按照官方文档的说法,对 __new()__ 的解释如下:
new() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation. 简单翻译: new() 主要用于允许对不可变类型,如 int, str, tuple ,来自定义如何创建他们的实例。它也可以用于在使用元类时重写,以便我们客制化类的创建
首先,我们来看下第一个作用,比如我们有一种需求,是一直要得到大写的字符串,类似新增一种数据类型,它会一直返回字符串的大写形式。我们就可以用 __new__ 来实现。示例如下:
class UpperStr(str): # 继承 str
def __new__(cls, value): # 重写 __new__ 来拦截创建实例对象的过程
# 在调用父类 __new__ 时,变成大写
return super(UpperStr, cls).__new__(cls, str.upper(value))
# 单纯用 __init__() 是无法实现的
# def __init(self, value):
# return super(UpperStr, cls).__init__(str.upper(value))
s = UpperStr("abc")
print(s) # ABC
其次第二个作用,就是我们通过使用元类来构造类时,可以通过重载元类的 __new__ 方法,修改 类定义 的行为。这个在后面专题讲 元类 时再详细介绍
- 除了上述作用,__new__ 还可以用于实现单例模式,原理也很简单,就是在创建实例对象时,先判断是否已经实例化。示例代码如下:
class MySingleton(object):
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(MySingleton, cls).__new__(cls)
m1 = MySingleton()
m2 = MySingleton()
print(id(m1) == id(m2)) # 可以用 id() 来判断是否是同一个实例对象,但一般不常用
print(m1 is m2) # 一般用 is 来判断
愿关注我们的人都能找到
属于自己的皮球
- 不可不知的基因组版本对应关系
- C++:istreambuf_iterator与istream_iterator的区别
- 【直播】我的基因组81:看看我的vcf文件的vaf分布情况
- c语言中函数参数处理顺序-从右向左
- HERD--位运算
- 一篇文章学会miRNA-seq分析
- HERD--GCC宏
- C++拷贝构造函数(深拷贝,浅拷贝)
- 安装glog和gflags
- FFmpeg_3.2.4+SDL_2.0.5学习(1)音视频解码帧及显示/播放数据
- FFmpeg_3.2.4+SDL_2.0.5学习(2)视频同步基础
- ubuntu17.04更换主题
- ubuntu17.04新安装之后的软件准备
- 打造一流编辑器vimplus
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Spark中的聚类算法
- 【Linux_Shell 脚本编程学习笔记六、shell的数值运算】
- Java自动化测试(adb常用命令 32)
- 前端学习计算机理论知识的好处
- 【Vue 学习笔记 一、Vue开发环境搭建】
- Vue 图片上传组件(base64 版):vue-upload-imgs
- 三、运行时的动态常量(学习笔记)
- Vue Cli 3 打包配置--自动忽略 console.log 语句
- git 常用命令介绍
- PAT (Basic Level) Practice (中文)1043 输出PATest (20 分)
- PAT (Basic Level) Practice (中文)1047 编程团体赛 (20 分)
- Vue中computed分析
- 半小时搞懂 HTTP、HTTPS和HTTP2
- RestPack Java实现Html转PDF文件
- 六、垃圾回收_判断对象是否存活算法_引用计数法详解