设为首页 收藏本站
查看: 951|回复: 0

[经验分享] Python: Overriding the __new__ method 覆盖__new__方法

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-12-24 08:37:38 | 显示全部楼层 |阅读模式
在构建诸如数字和字符串这样的内建类型的子类型时,或在其它别的一些场合时,会用到静态方法__new__。__new_先于__init__被调用,__new__是实例化对象的第一步。__new__的第一个参数就是类本身,其作用是用于返回类的一个实例。而__init__则没有返回。调用__init__时其第一个参数是实例本身。__init__的作用是初始化实例。存在着调用__new__来创建实例,而不需要用__init__来初始化实例的情况。但是却没有创建新的实例而不调用__new__的情况。
    需要知道,调用类来创建类实例的过程是调用类的__new__,并将类作为第一个参数。当返回类实例后,调用__init__来初始化该类实例。(这个过程是由metaclass的__call__来控制的)
下面的代码片段显示了override __new__的作用:



    class inch(float):
       "Convert from inch to meter"
       def __new__(cls, arg=0.0):
           return float.__new__(cls, arg*0.0254)

调用如下:
  print inch(12)    //输出0.3048
  
对比一下override __init__的情况:



    class inch(float):
       def __init__(self, arg=0.0):
           float.__init__(self, arg*0.0254)

Override __init__方法并不工作,因为float的__init__并不是一个操作:其会立即返回,忽略输入的参数。对于float这样的不可变内建类型,其__init__是dummy __init__,并没有任何实质操作。
(这样一来,那些不可变的类型能够保持其不可更改性,同时允许创建子类型。float类型的实例由其__init__进程初始化,可以通过调用__init__来改变已经存在的float对象的值。例如:
>>> # THIS DOESN'T WORK!!!
>>> import math
>>> math.pi.__init__(3.0)
>>> print math.pi
3.0
>>>

注意:在Python 2.7中,已经不能通过调用__init__来改变已经存在的实例对象了。
  
>>> import math
>>> print math.pi
3.14159265359
>>> math.pi.__init__(3.0)
>>> print math.pi
3.14159265359
>>>
  
下边是使用__new__的一些规则:
(1)__new__是静态方法
(2)传递给__new__的第一个参数必须是类,剩下的参数与构建方法相同
(3)override __new__方法会调用基类的__new__,而基类的__new__的第一个参数应该也是override __new__的类,而不是基类。
(4)一般情况下,子类的__new__的第一个参数是该类本身;如果需要,可以通过如下1)传递不同的参数给基类2)在结果对象创建后对其进行修改这两种方法来影响最终的返回对象
(5)__new__必须返回一个对象。通常情况下当然是返回新的子类对象。如果返回的是子类或其基类的已经存在的对象,则构建函数仍然会调用__init__。如果返回不同类的对象,则不会调用__init__。如果没有返回,Python不会将其设置为None
注意:在Python 2.7中,如果没有返回,Python会将其设置为None
例如



    class inch2(float):
       "Convert from inch to meter"
       def __new__(cls, arg=0.0):
           noreturn = float.__new__(cls, arg*0.0254)

测试:p = inch2(12)
     则p为None
(7)如果创建不可变类型的子类型,并且想加入一些可变的状态的话,最好是在__init__中添加,而不是在__new__中添加
(8)如果想要改变构造函数的signature,则需要同时override __new__和__init__。多数内建类型忽略传递给它们而它们并不使用参数。不可变类(如int, long, float, complex, str, unicode,和tuple)有一个dummy__init__,而可变类(如dict, list, file,staticmethod等)则有一个dummy __init__.内建的类型”object”则有dummy __new__ 和dummy __init__.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-38550-1-1.html 上篇帖子: python 读写文件程序 下篇帖子: python的字符串内建函数 method
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表