详解Python中的__new__、__init__、__call__三个特殊方法


Posted in Python onJune 02, 2016

__new__: 对象的创建,是一个静态方法,第一个参数是cls。(想想也是,不可能是self,对象还没创建,哪来的self)
__init__ : 对象的初始化, 是一个实例方法,第一个参数是self。
__call__ : 对象可call,注意不是类,是对象。

先有创建,才有初始化。即先__new__,而后__init__。
上面说的不好理解,看例子。

1.对于__new__

class Bar(object): 
  pass 
 
class Foo(object): 
  def __new__(cls, *args, **kwargs): 
    return Bar() 
 
print Foo()

 可以看到,输出来是一个Bar对象。

__new__方法在类定义中不是必须写的,如果没定义,默认会调用object.__new__去创建一个对象。如果定义了,就是override,可以custom创建对象的行为。
聪明的读者可能想到,既然__new__可以custom对象的创建,那我在这里做一下手脚,每次创建对象都返回同一个,那不就是单例模式了吗?没错,就是这样。可以观摩《飘逸的python - 单例模式乱弹》
定义单例模式时,因为自定义的__new__重载了父类的__new__,所以要自己显式调用父类的__new__,即object.__new__(cls, *args, **kwargs),或者用super()。,不然就不是extend原来的实例了,而是替换原来的实例。

2.对于__init__

使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候。例如:

# -*- coding: utf-8 -*-

class Person(object):
  """Silly Person"""

  def __init__(self, name, age):
    self.name = name
    self.age = age

  def __str__(self):
    return '<Person: %s(%s)>' % (self.name, self.age)

if __name__ == '__main__':
  piglei = Person('piglei', 24)
  print piglei

这样便是__init__最普通的用法了。但__init__其实不是实例化一个类的时候第一个被调用 的方法。当使用 Persion(name, age) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 __new__ 方法。

3.对于__call__
对象通过提供__call__(slef, [,*args [,**kwargs]])方法可以模拟函数的行为,如果一个对象x提供了该方法,就可以像函数一样使用它,也就是说x(arg1, arg2...) 等同于调用x.__call__(self, arg1, arg2) 。模拟函数的对象可以用于创建防函数(functor) 或代理(proxy).

class Foo(object): 
  def __call__(self): 
    pass 
 
f = Foo()#类Foo可call 
f()#对象f可call

总结,在Python中,类的行为就是这样,__new__、__init__、__call__等方法不是必须写的,会默认调用,如果自己定义了,就是override,可以custom。既然override了,通常也会显式调用进行补偿以达到extend的目的。
这也是为什么会出现"明明定义def _init__(self, *args, **kwargs),对象怎么不进行初始化"这种看起来诡异的行为。(注,这里_init__少写了个下划线,因为__init__不是必须写的,所以这里不会报错,而是当做一个新的方法_init__)

Python 相关文章推荐
python实现支持目录FTP上传下载文件的方法
Jun 03 Python
Python轻量级ORM框架Peewee访问sqlite数据库的方法详解
Jul 20 Python
python实现动态创建类的方法分析
Jun 25 Python
python3 线性回归验证方法
Jul 09 Python
python psutil模块使用方法解析
Aug 01 Python
python os.fork() 循环输出方法
Aug 08 Python
numpy np.newaxis 的实用分享
Nov 30 Python
将tensorflow模型打包成PB文件及PB文件读取方式
Jan 23 Python
python实现信号时域统计特征提取代码
Feb 26 Python
Django分组聚合查询实例分享
Apr 29 Python
关于python类SortedList详解
Sep 04 Python
Python 键盘事件详解
Nov 11 Python
Python实现优先级队列结构的方法详解
Jun 02 #Python
KMP算法精解及其Python版的代码示例
Jun 01 #Python
Python缩进和冒号详解
Jun 01 #Python
Python注释详解
Jun 01 #Python
深入理解python try异常处理机制
Jun 01 #Python
python学习 流程控制语句详解
Jun 01 #Python
python+Django+apache的配置方法详解
Jun 01 #Python
You might like
PHP调用VC编写的COM组件实例
2014/03/29 PHP
利用PHP实现一个简单的用户登记表示例
2017/04/25 PHP
PHP isset()及empty()用法区别详解
2020/08/29 PHP
用Javscript实现表单复选框的全选功能
2007/05/25 Javascript
top.location.href 没有权限 解决方法
2008/08/05 Javascript
jquery的$(document).ready()和onload的加载顺序
2010/05/26 Javascript
Jquery实现弹出层分享微博插件具备动画效果
2013/04/03 Javascript
JavaScript中实现依赖注入的思路分享
2015/01/15 Javascript
js拖拽的原型声明和用法总结
2016/04/04 Javascript
Javascript中的prototype与继承
2017/02/06 Javascript
JavaScript 数据类型详解
2017/03/13 Javascript
canvas基础绘制-绚丽倒计时的实例
2017/09/17 Javascript
jQuery读取本地的json文件(实例讲解)
2017/10/31 jQuery
解决node修改后需频繁手动重启的问题
2018/05/13 Javascript
基于Vue实现关键词实时搜索高亮显示关键词
2018/07/21 Javascript
JavaScript中变量、指针和引用功能与操作示例
2018/08/04 Javascript
Angular6 Filter实现页面搜索的示例代码
2018/12/02 Javascript
Vue.js实现的购物车功能详解
2019/01/27 Javascript
Vue数字输入框组件示例代码详解
2020/01/15 Javascript
Python 字符串操作方法大全
2014/03/11 Python
Python使用QRCode模块生成二维码实例详解
2017/06/14 Python
浅析PyTorch中nn.Linear的使用
2019/08/18 Python
Python:type、object、class与内置类型实例
2019/12/25 Python
TensorFLow 不同大小图片的TFrecords存取实例
2020/01/20 Python
Win10里python3创建虚拟环境的步骤
2020/01/31 Python
Python Selenium截图功能实现代码
2020/04/26 Python
Python 使用 PyQt5 开发的关机小工具分享
2020/07/16 Python
python list的index()和find()的实现
2020/11/16 Python
美国派对用品及装饰品网上商店:Shindigz
2016/07/30 全球购物
英国在线汽车和面包车零件商店:Car Parts 4 Less
2018/08/15 全球购物
泰国王权免税店官方网站:KingPower
2019/03/11 全球购物
彪马法国官网:PUMA法国
2019/12/15 全球购物
业务部门经理岗位职责
2014/02/23 职场文书
个人违纪检讨书
2014/09/15 职场文书
普通党员个人对照检查材料
2014/09/18 职场文书
nginx搭建NFS网络文件系统
2022/04/14 Servers