Python使用装饰器自动调用父类__init__
众所周知,Python中class的构造函数实际是__new__(),但是如果我们执行p1=Point()的时候,不仅会调用Point的__new__方法,而且会调用Point的__init__方法。由于python中所有都是对象,而所有对象的基类都是继承自object,而object实现的__new__基本都满足所有自定义类的要求,所以一般情况下,我们无需重新实现__new__,而只是关注__init__的实现,比如要初始化属性等都放在__init__中。python的这种机制直接导致,如果我们在父类的__init__中实现了一些逻辑,但是子类中又要遵循这些逻辑,就必须显式调用super(cls,self).__init__,在大量的自定义类中来显式调用父类的__init__,让人非常不爽。于是想,有没有一种方法可以让子类能自动隐式调用父类的__init__方法呢?
首先,想到的是python中的装饰器,能用装饰器来实现,最方便不过了,但这里需要解决2个问题:
1)p1=Point(),Point的__new__与__init__都会执行,我们必须将两者分开,能独立执行:创建Point的实例,调用super().__init__,再调用self.__init__
2)装饰器必须返回真实的实例:而不是其它对象
具体实现代码如下:
- #使用装饰器自动调用父类的无参__init__方法
- def super_init_wrapper(origin_cls):
- super_class=origin_cls.mro()[1]
- class WrapperClass:
- def __new__(cls,*args,**kwargs):
- #print('origin class',origin_cls)
- instance= object.__new__(origin_cls,*args,**kwargs)
- super_class.__init__(instance)
- instance.__init__(*args,**kwargs)
- return instance
- return WrapperClass
- class Base:
- def __init__(self):
- self.x=100
- print('Base init')
- @super_init_wrapper
- class Instance(Base):
- def __init__(self,a,b,c):
- self.a=a
- self.b=b
- self.c=c
- print('Instance init')
- if __name__=='__main__':
- ins=Instance('a','b','c')
- #ins= super_init_wrapper(Instance)('a','b','c')
- print(isinstance(ins,Base))
- print(type(ins))
- print(ins.x)
- import inspect
- #kcargs的格式super参数名=self参数名的形式,比如x='{x}'
- def auto_super_initial(**kcargs):
- def decrorate(self_cls):
- base_cls=self_cls.mro()[1]
- class DecorateClass:
- def __new__(cls,*args,**kwargs):
- self=object.__new__(self_cls,*args,**kwargs)
- sig=inspect.signature(self.__init__)
- init_args=sig.bind_partial(*args,**kwargs).arguments
- #构造调用super.__init__的参数
- super_args={name:eval(str(value).format(**init_args)) for name,value in kcargs.items()}
- base_cls.__init__(self,**super_args)
- self_cls.__init__(self,*args,**kwargs)
- return self
- return DecorateClass
- return decrorate
- class Point:
- def __init__(self,x=0,y=0):
- self.x=x
- self.y=y
- class Line(Point):
- def __init__(self,x=0,y=0,length=0):
- super(Triangle,self).__init__(x,y)
- self.length=length
- @auto_super_initial(x='{x}+{y}',y='{y}')
- class Rectangle(Point):
- def __init__(self,x=0,y=0,width=0,height=0):
- self.width=width
- self.height=height
- if __name__=='__main__':
- rect=Rectangle(1,10,10,10)
- print(rect.x,rect.y) #11 10
Python使用装饰器自动调用父类__init__的更多相关文章
- python 解除装饰器,调用原本函数。
假设fun函数被装饰器装饰了,name调用fun,就不是调用fun本身了,那么如何继续调用本身呢.使用fun_raw = fun.__wrapped__这样使用fun_raw就是调用没被装饰器修饰后的 ...
- Python装饰器的调用过程
在Python学习的过程中,装饰器是比较难理解的一个应用.本人也在学习期间也遇到很多坑,现将装饰器的基本调用过程总结一下. 首先,装饰器用到了“闭包”,而“闭包”是学习装饰器的基础,所以在讲装饰器之前 ...
- python 多个装饰器的调用顺序
python 多个装饰器的调用顺序 一般情况下,在函数中可以使用一个装饰器,但是有时也会有两个或两个以上的装饰器.多个装饰器装饰的顺序是从里到外(就近原则),而调用的顺序是从外到里(就远原则). 原代 ...
- Python:装饰器是如何调用的
应用举例:(1)装饰器 # 装饰器的调用: # 一旦用上装饰器会: # 第一步:调outer函数 # 第二步:被装饰的函数play_game会被当作参数fn给outer # 第三步:最后调用play_ ...
- Python各式装饰器
Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...
- python基础——装饰器
python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...
- 【转】详解Python的装饰器
原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
- 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档
转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...
- 详解Python的装饰器
Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...
随机推荐
- 【PostgreSQL-9.6.3】log参数的设置
编辑数据目录中的postgresql.conf参数文件,我的数据目录是/usr/local/pgsql/data vi postgresql.conf 找到如下内容: ... #----------- ...
- jQuery顺序加载图片(终版)
这一篇是对上一篇(jQuery顺序加载图片(初版)--http://www.cnblogs.com/newbie-cc/p/3707504.html)的改进. function loadImage(i ...
- Caffe2:使用Caffe构建LSTM网络
前言: 一般所称的LSTM网络全叫全了应该是使用LSTM单元的RNN网络. 原文:(Caffe)LSTM层分析 入门篇:理解LSTM网络 LSTM的官方简介: http://deeplearning. ...
- (转) OpenLayers3基础教程——加载资源
概述: 本节讲述如何在Ol3中加载wms图层并显示到地图中. Ol3下载: 你可以在OL官网去下载,下载地址为http://openlayers.org/download/,也可以去我的百度云盘下载, ...
- ivew使用星星评分
这组件好像有问题,不知道是我们项目环境造成的还是什么,初始化半星不能正常显示,显示的全星. 1.template <div style="display:inline-block;ma ...
- 回文词(Palindromes, UVa401)
输入一个字符串,判断它是否为回文串以及镜像串.输入字符串保证不含数字0. 所谓 回文串,就是反转以后和原串相同,如abba和madam. 所谓镜像串,就是左右镜像之后和原串相同,如2S和3AIAE. ...
- POJ3253 Fence Repair【贪心】
我们的小伙伴Bingo真的很调皮,他在上课的路上看到树上有个鸟窝,他就想去把他捅下来,但是鸟窝很高他够不到,于是他就到处找木棍,想把这些木棍接在一起,然后去捅鸟窝.他一共找了N跟木棍 (1 ≤ N ≤ ...
- 08.Web服务器-1.浏览器访问服务器显示页面的网络模型步骤解析
- 爬虫系列(五) re的基本使用
1.简介 究竟什么是正则表达式 (Regular Expression) 呢?可以用下面的一句话简单概括: 正则表达式是一组特殊的 字符序列,由一些事先定义好的字符以及这些字符的组合形成,常常用于 匹 ...
- Windows Server 2008 R2x64 IIS7+PHP5.6 错误 500.0
这两天准备升级一个网站项目,新项目基于PHP并进行了ZendGuard加密,需要在PHP5.6版本中运行 而客户之前的运行环境是php5.2~5.4,那好,再新建一个PHP版本不就完事了吗!!! 于是 ...