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 ...
随机推荐
- android黑科技系列——分析某直播App的协议加密原理以及调用加密方法进行协议参数构造
一.前言 随着直播技术火爆之后,各家都出了直播app,早期直播app的各种请求协议的参数信息都没有做任何加密措施,但是慢慢的有人开始利用这个后门开始弄刷粉关注工具,可以让一个新生的小花旦分分钟变成网红 ...
- 联想VIBE Shot(Z90-7/全网通) 解锁BootLoader
工具下载链接: http://pan.baidu.com/s/1dF7zGTb 备用下载链接: http://pan.baidu.com/s/1i4UHP4L 本篇教程教你如何傻瓜式解锁BootLoa ...
- Java_Web之神奇的Ajax
为什么使用Ajax? 无刷新:不刷新整个页面,只刷新局部 无刷新的好处 提供类似C/S的交互效果,操作更方面 只更新部分页面,有效利用带宽 什么是Ajax? XMLHttpRequest常用方 ...
- 【转载】使用IntelliJ IDEA提示找不到struts-default文件
创建strus,参考文如下: https://blog.csdn.net/u010358168/article/details/79769137 使用IntelliJ IDEA创建struts2工程时 ...
- jmeter3.1 压测
压测目标:error 为0,线程起到250,服务器配置达到最大 一.Jmeter3.1 压测 JMeter3.1提供一个用于生成HTML页面格式图形化报告的扩展模块.该模块支持通过两种方式生成多维度图 ...
- php第九节课
面向对象 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...
- 【JavaScript框架封装】使用原生js封装的类似于JQuery的框架及核心源码分享(多文件版本)
这个版本的JQuery是对上一个版本的JQuery,使用了require.js进行了二次封装,基本上把前面的每一个框架封装成为一个单独的模块,最终的目录结构如下: 由于代码量和目录比较多,这个封装好的 ...
- [luogu1640 SCOI2010]连续攻击游戏 (二分图最大匹配)
传送门 Description lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某 ...
- Java基础学习总结(67)——Java接口API中使用数组的缺陷
如果你发现在一个接口使用有如下定义方法: public String[] getParameters(); 那么你应该认真反思.数组不仅仅老式,而且我们有合理的理由避免暴露它们.在这篇文章中,我将试图 ...
- HDU 4359 Easy Tree DP?
Easy Tree DP? Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...