标签: 继承

  • Python 继承使用super出错

    Python 2.2以后使用super继承的父类属性的时候会报错,这篇文章通过讲解新式类和旧类的区别来解决super报错的问题。

    在Python的类中去继承父类的属性, 一般的写法为:

    [python]
    class Father:
    def __init__(self):
    print "I’m Father"

    class Child(Father):
    def __init__(self):
    Father.__init__(self)
    print "I’m Child"
    >>>f = Child()
    I’m Father
    I’m Child
    [/python]

    如果在多重继承的问题中,例如菱形继承(钻石问题),则需要用到super来解决。但是super只能用在继承基类”object”的新式类中,不能用于以前的经典类,否则报错:

    [python]
    class Father:
    def __init__(self):
    print "I’m Father"

    class Child(Father):
    def __init__(self):
    super(Child, self).__init__()
    print "I’m Child"
    >>>f = Child()
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 3, in __init__
    TypeError: must be type, not classobj
    [/python]

    原因如下:

    解决的方法是设置Father继承Object

    [python]
    class Father(object):
    def __init__(self):
    print "I’m Father"

    class Child(Father):
    def __init__(self):
    super(Child, self).__init__()
    print "I’m Child"
    >>>f = Child()
    I’m Father
    I’m Child
    [/python]

    以下关于《旧类和新式类》的内容摘自:http://blog.csdn.net/jb19900111/article/details/20228341

    • python的新式类是2.2版本引进来的,我们可以将之前的类叫做经典类或者旧类。
    • 为什么要在2.2中引进new style class呢?官方给的解释是:为了统一类(class)和类型(type)。
    • 在2.2之前,比如2.1版本中,类和类型是不同的,如a是ClassA的一个实例,那么a.__class__返回 ‘ class __main__.ClassA‘ ,type(a)返回总是<type ‘instance’>。而引入新类后,比如ClassB是个新类,b是ClassB的实例,b.__class__和type(b)都是返回‘class ‘__main__.ClassB’ ,这样就统一了。
    • 引入新类后,还有其他的好处,比如更多的内置属性将会引入,描述符的引入,属性可以来计算等等。
    • 为了向前兼容,默认情况下用户定义的类为经典类,新类需要继承自所有类的基类 object 或者继承自object的新类。
    • 值得注意的地方是,虽然使用的是最新的python(2.7),但是一些特性不会在旧式类起作用。
    • 所以,为了确保自己使用的是新式类,有以下方法:
      • 把这个赋值语句放在类模块代码的最前面 __metaclass__ = type(前面有提过)。
      • 自己的类都从内建类object直接或者间接地继承。
      • 如果不需要兼容旧式类,旧版本的类,那么就保持都是新式类。
      • 当然,在Python3里面,不存在这些问题了,因为所有的类都是object类的子类(隐式)。