重写是继承机制中的重要内容,对于构造方法尤为重要。构造方法用来初始化新建对象的状态,大多数子类不仅要有自己的初始化代码,还要拥有超类的初始化代码。
如果一个类的构造方法被重写,那么就需要调用超类的构造方法,否则对象可能不会被正确的初始化–Python基础教程
将上述思想进行实践.
python 2.7
IDE Pycharm 5.0.3
当前,我们先定义一个大的父类,用Bird来创建,里面有个构造方法和定义了两个方法,分别是eat,sing方法,然后创建了一个Sparrow的子类,继承自父类Bird,自己也拥有构造方法,首先进行测试
class Bird:
def __init__(self):
print '我是父类的初始化'
self.cansing = True
def eat(self):
print 'i can eat'
def sing(self):
if self.cansing:
print 'i can sing'
class Sparrow(Bird):
def __init__(self):
print '我就是要重写父类的init'
def jump(self):
print 'i can jump'
S = Sparrow()
S.jump()
S.eat()
S.sing()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
然后很喜闻乐见的报错了,因为子类重写了父类的构造方法,我的理解是被覆盖了而不是像append那样接上,所以结果如图:
这里显示了能够正常调用父类的其他方法,但是构造方法被重写后调用不了
这里的解决方法就存在两种,一种是调用未绑定的超类构造方法,这个方法在python2.2使用较多,之后随着super出现后,被取缔,原因也有很多,这个具体自己百度吧。
先放上用未绑定的超类构造方法:
class Bird:
def __init__(self):
print '我是父类的初始化'
self.cansing = True
def eat(self):
print 'i can eat'
def sing(self):
if self.cansing:
print 'i can sing'
class Sparrow(Bird):
def __init__(self):
Bird.__init__(self)
print '我就是要重写父类的init'
def jump(self):
print 'i can jump'
S = Sparrow()
S.jump()
S.eat()
S.sing()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
效果如下,可以看出,父类的构造方法被调用,这才是我们真正需要的继承方法,即像append那样填充式继承。
这里写图片描述
这个方法个人来看并不推荐,因为如果要修改很多很多子类,若是父类名字一变,修改量太大,而且,对父类的访问着实很多次。
另一种方式就是使用super,记得这是个只能在新式类中才起作用,所以代码块前需要加
__metaclass__ = type
- 1
完整代码块如下:
__metaclass__ = type
class Bird:
def __init__(self):
print '我是父类的初始化'
self.cansing = True
def eat(self):
print 'i can eat'
def sing(self):
if self.cansing:
print 'i can sing'
class Sparrow(Bird):
def __init__(self):
super(Sparrow,self).__init__()
print '我就是要重写父类的init'
def jump(self):
print 'i can jump'
S = Sparrow()
S.jump()
S.eat()
S.sing()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
效果和上述采用未绑定的超类方法一样,但是更加直观。下面盗用一下为什么super方法那么超级:
即使类已经继承多个超类,它也只需要使用一次super函数
6.29更新–关于Tkinter中Frame类是旧类的判断
接触Tk,看着教程写到:
def __init__(self, master=None):
Frame.__init__(self, master)
- 1
- 2
想着能不能用super的方法呢,不是一直在提倡super么,结果试了一下,
def __init__(self,master=None):
super(Application, self).__init__()
- 1
- 2
报错:
TypeError: must be type, not classobj
- 1
结果查看了一下父类Frame类型;
In[3]: issubclass(Frame, object)#判断是否为新类
Out[3]: False
- 1
- 2
显示Frame是旧类,所以不能和新类混着用,这里记上一笔。