Python面向对象中的old-style and new-style classes

old-style and new-style 区分问题的引出

Python刚入门者或者因为业务接触Python的同学们,大多从Python3入手(现在很多的规范都是基于3展开)。但是由于历史原因,很多老旧业务的服务还是基于Python2,这就会造成很多不理解2与3版本差异的同学莫名碰到一些问题,old-style and new-style就是面向对象编程时会遇到的一个问题。

问题描述

子类ElectricCar继承基类Car
基类 Car:

class Car:
    def __init__(self, speed):
        self.speed = speed

子类 ElectricCar:

class ElectricCar(Car):
    def __init__(self, speed):
    	super(ElectricCa, self).__init__(speed)

在python3.x环境下,子类调用基类正常,但是在python2.x环境下,出现报错TypeError: super() argument 1 must be type, not classobj

问题分析

使用super调用基类,需要调用的基类是基于new-style class。在python3.x中不管基类的写法(隐式继承了object),默认任何类都是new-style class,所以在3.x环境中何种操作都不会引发错误。至于报错的内容,接下来介绍old-style和new-style差异的时候会提及。

old-style and new-style差异

在python最早的版本,old-style是用户的唯一选择,这种专制局面一直维持到2.1版本。old-style class存在两个不相关的概念:“type"和"class”,例如Car().__class__为Car所属的类,type(Car())为Car的固定type <type ‘instance’>,从这一点可以推测出old-style class唯一继承名为"instance"的type。2.2版本开始为了统一"type"和"class"的概念引入了new-style,自此这个困扰的问题终于得到解决。
回到开始的报错内容,此处通过实例解释:
新建new-style class Car1:

class Car1(object):
    def __init__(self, speed):
        self.speed = speed
>>> type(Car)
<type 'classobj'>
>>> type(Car1)
<type 'type'>

所以new-style class使用super()方法会报无法引用old-style class的错误

new-style相对old-style的一些重要变更
  • 引入super()
    使用super()可以隐式访问已经被重写的基类方法注意super()是new-style特有的,明确这一点能有效避免新、旧混用。
  • MRO 变更
  • 新增descriptors
    参考链接
  • 新增__slots__

解决办法

通过上面的介绍,已经有了一个解决办法。在这里给出两个解决办法:

  • 统一基类的style
    将基类规范为new-style
class Car(object):
    def __init__(self, speed):
        self.speed = speed
  • 在子类中显式出继承的基类,同时固化继承的基类
class ElectricCar(Car):
    def __init__(self, speed):
    	Car.__init__(self, speed)

总结

  • 形成习惯,避免混用的情况
  • 跟进python发展趋势使用new-style classes
参考链接
  1. https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes
  2. https://stackoverflow.com/questions/54867/what-is-the-difference-between-old-style-and-new-style-classes-in-python#comment37474285_54873
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值