基于文章:Why is init() always called after new()?

特别说明:

  1. 这篇文章的灵感来源于stackoverflow的一个提问,准确说,我只是做了些知识梳理的工作,对其中的优秀回答进行了总结和提炼,旨在帮助自己和读者对此有个深刻的认识。

  2. 本文章节中的new是__new__的简写,init是__init__的简称,只是为了语言叙述的方便而做出的省略。

Part I: 为什么new总是先于init?

new是静态的类方法,static method。

init是实例方法

它们有不同的参数与返回值:

  1. new的参数总是:cls 返回值总是self
  2. init的参数总是:self 总是无返回值

Part II: 三段代码的思考

Block 1: 基于原文的代码

class B(object):
_dict = dict() def __new__(cls):
if 'key' in B._dict:
print("EXISTS:", B._dict['key'])
return B._dict['key']
else:
print("NEW")
return super(B, cls).__new__(cls) def __init__(self):
print("INIT")
B._dict['key'] = self
print("") b1 = B()
b2 = B()
b3 = B() # 运行结果如下:
NEW
INIT EXISTS: <__main__.B object at 0x0000028F29820828>
INIT EXISTS: <__main__.B object at 0x0000028F29820828>
INIT

关于原文中的代码解释:

在每次实例化之前,也就是new的操作时,都查询了是否存在第一个实例。在第一次初始化时,把第一个实例self赋值给了类的公有属性:test_dict。之后的每次实例化之前,new都会查询到它(实例)已经存在,new并且总是返回了第一个实例给了init。然后init参与对该实例(总是第一个实例)进行构建工作。

我只能揣测,原问题的作者似乎意外创建了一个单例的类。你可以在init中执行print(self),会发现打印出来的对象总是第一个实例。当然,如果确实是想要实现单例模式,应该使用装饰器。即:

def singleton(cls):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return getinstance @singleton
class MyClass:
...

为什么instances使用的是字典?因为Python总是用字典去存储一个新的实例,并且init中的属性也同样以字典的方法存储的。当然,如果你想节约内存,不使用字典而用列表,可以重载new方法,或者使用__slot__

Block 2: 基于Block 1 的修改

class A(object):
test_dict = dict() def __new__(cls):
if 'key' in A.test_dict:
print("EXISTS:", A.test_dict['key'])
return A.test_dict['key']
else:
print("NEW")
return super(A, cls).__new__(cls) def __init__(self):
print("INIT")
if 'key' in A.test_dict:
print('修改')
A.test_dict['key'] += 1
else:
print('第一次创建')
A.test_dict['key'] = 0
print('') a1 = A()
a2 = A()
a3 = A()

Block 3: 基于Block 2 的修改

class A(object):
test_dict = dict() 1.类的公有属性 def __new__(cls): 2.执行__new__
if 'key' in A.test_dict:
print("EXISTS:", A.test_dict['key'])
return super(A, cls).__new__(cls)
else:
print("NEW")
return super(A, cls).__new__(cls) def __init__(self):
print("INIT")
if 'key' in A.test_dict:
print('修改')
A.test_dict['key'] += 1
else:
print('第一次创建')
A.test_dict['key'] = 0
print('') a1 = A()
a2 = A()
a3 = A()

Q&A

  1. new 总是先于 int 执行,为什么?

    答:

    注意事项: new是类的静态方法,

    Use new when you need to control the creation of a new instance.

    Use init when you need to control initialization of a new instance.

    前者用于控制创建一个新实例,后者用于控制对该新实例进行初始化。

精要:

它们负责的工作不同:前者负责创建新实例,后者负责实例初始化

它们服务的层级不同:前者是cls(类),后者是self(实例本身)

__new__是秘书给领导打工,后者领导的一众小弟们打工。

  1. 为什么上述代码的__init__没有被执行,而下面的每次都正常执行了?

    答:

    用于我在上述代码中恶意使用了new, 没有对new进行返回实例。

    new__总是第一个被Call(调用),并且他的返回值:当且仅当是一个新的实例!!

    代码1中,并没有返回这个新的实例,第一次实例化对象,自动进行了__int
    ,后面的,

    都是只创建了新示例

python的new与init的更多相关文章

  1. python中self cls init的理解

    原创文章,未经允许禁止转载! python中self cls init的理解 python中self cls init的理解

  2. 创建一个python类 ,self init相关参数的简单介绍

    一 创建 ''' 一 使用python 语法 创建一个类, 探究self 是干啥的 1 创建一个对象 car 2 写入两个行参 3 定义两个方法 ''' class Car(): ''' 二 init ...

  3. python 子类中定义init方法

  4. boost.python笔记

    boost.python笔记 标签: boost.python,python, C++ 简介 Boost.python是什么? 它是boost库的一部分,随boost一起安装,用来实现C++和Pyth ...

  5. python面向对象基础

    面向对象基础 1. 简述 编程方式: 面向过程: 根据代码在脚本的堆叠顺序,从上到下依次执行 函数式编程:将相同功能的代码封装到函数中,直接调用即可,减少代码重复性 面向对象:对函数进行分类和封装,将 ...

  6. 12岁的少年教你用Python做小游戏

    首页 资讯 文章 频道 资源 小组 相亲 登录 注册       首页 最新文章 经典回顾 开发 设计 IT技术 职场 业界 极客 创业 访谈 在国外 - 导航条 - 首页 最新文章 经典回顾 开发 ...

  7. python自学笔记

    python自学笔记 python自学笔记 1.输出 2.输入 3.零碎 4.数据结构 4.1 list 类比于java中的数组 4.2 tuple 元祖 5.条件判断和循环 5.1 条件判断 5.2 ...

  8. python开发部署时新增数据库中表的方法

    在项目版本让运维部署时,涉及到数据库表的增加问题,想了一下,可以有四种方法 1.使用SQLAlchemy的db.create_all()方法 # -*- coding:utf-8 -*- from f ...

  9. 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(上)

    目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构   前言 学习Python也有一个半月时间了,学到现在感觉 ...

随机推荐

  1. 关系型数据库 RDS(Relational Database Service),知识点

    资料 网址 官方介绍 https://help.aliyun.com/document_detail/26092.html?spm=5176.2020520104.0.0.2b4b1450yqd1gg ...

  2. Gym - 102056C(2018EC final) -Heretical … Möbius ——CRT

    题意 给出一个长为200的01序列,判断是否在前1e9个莫比乌斯*值中.(这里的莫比乌斯值加了绝对值) 分析 意到因为4的倍数一定是0,9的倍数一定是0……169的倍数一定是0.那么我们可以对4,9, ...

  3. jdk,jre,jvm,openJdk

    1,jdk install: java_home: point to the installation directory of JDK, which is used by some java dev ...

  4. 第02组Beta冲刺(3/4)

    队名:十一个憨批 组长博客 作业博客 组长黄智 过去两天完成的任务:了解整个游戏的流程 GitHub签入记录 接下来的计划:继续完成游戏 还剩下哪些任务:完成游戏 燃尽图 遇到的困难:没有美术比较好的 ...

  5. MHA+keepalived集群环境搭建

    整个MHA+keepalived集群环境搭建 1.1. 环境简介1.1.1.vmvare虚拟机,系统版本CentOS6.5 x86_64位最小化安装,mysql的版本5.7.21,1.1.2.虚拟机器 ...

  6. [Gamma]Scrum Meeting#6

    github 本次会议项目由PM召开,时间为6月1日晚上10点30分 时长10分钟 任务表格 人员 昨日工作 下一步工作 木鬼 撰写博客,组织例会 撰写博客,组织例会 swoip 前端显示屏幕,翻译坐 ...

  7. 【操作系统之五】Linux常用命令之grep

    一.概念grep(Global search Regular Expression and Print out the line)强大的文本搜索工具,从文本文件或管道数据流中筛选匹配的行及数据,并把匹 ...

  8. 三个基于.net的浏览器内核使用的比较

    最近做模拟登陆发帖相关的项目 分别尝试了基于IE .NET自带的 webbrowser 和 基于WebKit 的WebKit.NET和openWebkitSharp 最开始肯定是用的.NET自带的we ...

  9. Java一个对象占用多少字节

    虚拟机:Java HotSpot(TM) 64-Bit Server VM (25.221-b11, mixed mode) 对象的内存以字节为单位,且必须是8的倍数,它的构成由3部分组成:对象头+实 ...

  10. 【06月19日】A股滚动市盈率PE最低排名

    ​仅根据最新的市盈率计算公式进行排名,无法对未来的业绩做出预测. 方大集团(SZ000055) - 滚动市盈率PE:2.59 - 滚动市净率PB:1.16 - 滚动年化股息收益率:3.91% - 建筑 ...