基于文章: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. flask实战-个人博客-数据库-生成虚拟数据 --

    3.生成虚拟数据 为了方便编写程序前台和后台功能,我们在创建数据库模型后就编写生成虚拟数据的函数. 1)管理员 用于生成虚拟管理员信息的fake_admin()函数如下所示: personalBlog ...

  2. linux服务器NAT后无法在内网通过外部IP访问内部服务的问题

    场景一: 将外网访问192.168.100.10的80端口转发到192.168.75.5:8000端口. # iptables -t nat -A PREROUTING -d 192.168.100. ...

  3. JDOJ 1606 数字三角形

    JDOJ 1606: 数字三角形 JDOJ传送门 Description 输入n,输出n的数字三角形 见样例 Input n Output n的数字三角形 Sample Input 4 Sample ...

  4. 第二阶段冲刺(个人)——three

    今天的个人计划:选择功能界面的选择框排版设计.使得一些选择功能当点击鼠标事件后才会出现. 昨天做了什么?测试登录功能并优化. 遇到了什么困难?一些js函数的运用不熟悉,好多借助了百度.

  5. Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging

    1665 - Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT a ...

  6. 从三数之和看如何优化算法,递推-->递推加二分查找-->递推加滑尺

    人类发明了轮子,提高了力的使用效率. 人类发明了自动化机械,将自己从重复的工作中解脱出来. 提高效率的方法好像总是离不开两点:拒绝无效劳动,拒绝重复劳动.人类如此,计算机亦如是. 前面我们说过了四数之 ...

  7. Spring Boot 知识笔记(servlet、监听器、拦截器)

    一.通过注解自定义servlet package net.Eleven.demo.servlet; import javax.servlet.ServletException; import java ...

  8. LDoc使用总结

    LDoc使用总结 安装 按照下面的安装就可以了 http://www.cnblogs.com/ZhYQ-Note/articles/6022525.html 使用 参考:官方的说明文档 https:/ ...

  9. 【计算机视觉】BRIEF特征匹配

    Binary Robust Independent Elementary Features www.cnblogs.com/ronny 1. BRIEF的基本原理 我们已经知道SIFT特征采用了128 ...

  10. sql实现MD5加密

    select substring(sys.fn_sqlvarbasetostr(HashBytes('MD5','test')),3,32)