众所周知,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)装饰器必须返回真实的实例:而不是其它对象

具体实现代码如下:

  1. #使用装饰器自动调用父类的无参__init__方法
  2. def super_init_wrapper(origin_cls):
  3. super_class=origin_cls.mro()[1]
  4. class WrapperClass:
  5. def __new__(cls,*args,**kwargs):
  6. #print('origin class',origin_cls)
  7. instance= object.__new__(origin_cls,*args,**kwargs)
  8. super_class.__init__(instance)
  9. instance.__init__(*args,**kwargs)
  10. return instance
  11. return WrapperClass
  12.  
  13. class Base:
  14. def __init__(self):
  15. self.x=100
  16. print('Base init')
  17.  
  18. @super_init_wrapper
  19. class Instance(Base):
  20. def __init__(self,a,b,c):
  21. self.a=a
  22. self.b=b
  23. self.c=c
  24. print('Instance init')
  25.  
  26. if __name__=='__main__':
  27. ins=Instance('a','b','c')
  28. #ins= super_init_wrapper(Instance)('a','b','c')
  29. print(isinstance(ins,Base))
  30. print(type(ins))
  31. print(ins.x)
  1. import inspect
  2. #kcargs的格式super参数名=self参数名的形式,比如x='{x}'
  3. def auto_super_initial(**kcargs):
  4. def decrorate(self_cls):
  5. base_cls=self_cls.mro()[1]
  6. class DecorateClass:
  7. def __new__(cls,*args,**kwargs):
  8. self=object.__new__(self_cls,*args,**kwargs)
  9. sig=inspect.signature(self.__init__)
  10. init_args=sig.bind_partial(*args,**kwargs).arguments
  11. #构造调用super.__init__的参数
  12. super_args={name:eval(str(value).format(**init_args)) for name,value in kcargs.items()}
  13. base_cls.__init__(self,**super_args)
  14. self_cls.__init__(self,*args,**kwargs)
  15. return self
  16. return DecorateClass
  17. return decrorate
  18.  
  19. class Point:
  20. def __init__(self,x=0,y=0):
  21. self.x=x
  22. self.y=y
  23.  
  24. class Line(Point):
  25. def __init__(self,x=0,y=0,length=0):
  26. super(Triangle,self).__init__(x,y)
  27. self.length=length
  28.  
  29. @auto_super_initial(x='{x}+{y}',y='{y}')
  30. class Rectangle(Point):
  31. def __init__(self,x=0,y=0,width=0,height=0):
  32. self.width=width
  33. self.height=height
  34.  
  35. if __name__=='__main__':
  36. rect=Rectangle(1,10,10,10)
  37. print(rect.x,rect.y) #11 10

Python使用装饰器自动调用父类__init__的更多相关文章

  1. python 解除装饰器,调用原本函数。

    假设fun函数被装饰器装饰了,name调用fun,就不是调用fun本身了,那么如何继续调用本身呢.使用fun_raw = fun.__wrapped__这样使用fun_raw就是调用没被装饰器修饰后的 ...

  2. Python装饰器的调用过程

    在Python学习的过程中,装饰器是比较难理解的一个应用.本人也在学习期间也遇到很多坑,现将装饰器的基本调用过程总结一下. 首先,装饰器用到了“闭包”,而“闭包”是学习装饰器的基础,所以在讲装饰器之前 ...

  3. python 多个装饰器的调用顺序

    python 多个装饰器的调用顺序 一般情况下,在函数中可以使用一个装饰器,但是有时也会有两个或两个以上的装饰器.多个装饰器装饰的顺序是从里到外(就近原则),而调用的顺序是从外到里(就远原则). 原代 ...

  4. Python:装饰器是如何调用的

    应用举例:(1)装饰器 # 装饰器的调用: # 一旦用上装饰器会: # 第一步:调outer函数 # 第二步:被装饰的函数play_game会被当作参数fn给outer # 第三步:最后调用play_ ...

  5. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  6. python基础——装饰器

    python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...

  7. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

  8. 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档

    转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...

  9. 详解Python的装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

随机推荐

  1. 【PostgreSQL-9.6.3】log参数的设置

    编辑数据目录中的postgresql.conf参数文件,我的数据目录是/usr/local/pgsql/data vi postgresql.conf 找到如下内容: ... #----------- ...

  2. jQuery顺序加载图片(终版)

    这一篇是对上一篇(jQuery顺序加载图片(初版)--http://www.cnblogs.com/newbie-cc/p/3707504.html)的改进. function loadImage(i ...

  3. Caffe2:使用Caffe构建LSTM网络

    前言: 一般所称的LSTM网络全叫全了应该是使用LSTM单元的RNN网络. 原文:(Caffe)LSTM层分析 入门篇:理解LSTM网络 LSTM的官方简介: http://deeplearning. ...

  4. (转) OpenLayers3基础教程——加载资源

    概述: 本节讲述如何在Ol3中加载wms图层并显示到地图中. Ol3下载: 你可以在OL官网去下载,下载地址为http://openlayers.org/download/,也可以去我的百度云盘下载, ...

  5. ivew使用星星评分

    这组件好像有问题,不知道是我们项目环境造成的还是什么,初始化半星不能正常显示,显示的全星. 1.template <div style="display:inline-block;ma ...

  6. 回文词(Palindromes, UVa401)

    输入一个字符串,判断它是否为回文串以及镜像串.输入字符串保证不含数字0. 所谓 回文串,就是反转以后和原串相同,如abba和madam. 所谓镜像串,就是左右镜像之后和原串相同,如2S和3AIAE. ...

  7. POJ3253 Fence Repair【贪心】

    我们的小伙伴Bingo真的很调皮,他在上课的路上看到树上有个鸟窝,他就想去把他捅下来,但是鸟窝很高他够不到,于是他就到处找木棍,想把这些木棍接在一起,然后去捅鸟窝.他一共找了N跟木棍 (1 ≤ N ≤ ...

  8. 08.Web服务器-1.浏览器访问服务器显示页面的网络模型步骤解析

  9. 爬虫系列(五) re的基本使用

    1.简介 究竟什么是正则表达式 (Regular Expression) 呢?可以用下面的一句话简单概括: 正则表达式是一组特殊的 字符序列,由一些事先定义好的字符以及这些字符的组合形成,常常用于 匹 ...

  10. Windows Server 2008 R2x64 IIS7+PHP5.6 错误 500.0

    这两天准备升级一个网站项目,新项目基于PHP并进行了ZendGuard加密,需要在PHP5.6版本中运行 而客户之前的运行环境是php5.2~5.4,那好,再新建一个PHP版本不就完事了吗!!! 于是 ...