读django类视图代码时,遇到这样一个问题:
class A(object): def __init__(self): pass def get_data(self, **kwargs): print "enter A" if "A" not in kwargs: kwargs['A'] = "value A" print "leave A" return kwargsclass B(A): def get_data(self, **kwargs): print "enter B" if "B" not in kwargs: kwargs['B'] = "value B" print "leave B" return super(B, self).get_data(**kwargs)class C(A): def get_data(self, **kwargs): print "enter C" if "C" not in kwargs: kwargs['C'] = "value C" print "leave C" return super(C, self).get_data(**kwargs)class D(C, B): def use_data(self): print "enter D" data = self.get_data(D="value D") print "data value:",data print "leave D" returnif __name__ =="__main__": d = D() d.use_data()
这套程序中,D的use_data函数中的data的值应该是什么,这里的运行结果是:
enter Denter Cleave Center Bleave Benter Aleave Adata value: {'A': 'value A', 'C': 'value C', 'B': 'value B', 'D': 'value D'}leave D
需要注意的是:这里的A必须继承object,如果A不继承object,程序变成这样:
class A(): def __init__(self): pass def get_data(self, **kwargs): print "enter A" if "A" not in kwargs: kwargs['A'] = "value A" print "leave A" return kwargsclass B(A): def get_data(self, **kwargs): print "enter B" if "B" not in kwargs: kwargs['B'] = "value B" print "leave B" return super(B, self).get_data(**kwargs)class C(A): def get_data(self, **kwargs): print "enter C" if "C" not in kwargs: kwargs['C'] = "value C" print "leave C" return super(C, self).get_data(**kwargs)class D(C, B): def use_data(self): print "enter D" data = self.get_data(D="value D") print "data value:", data print "leave D" returnif __name__ =="__main__": d = D() d.use_data()
运行结果会报错:
/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/apple/mygit/kd/demo/class_inheritance_example.pyTraceback (most recent call last):enter D File "/Users/apple/mygit/kd/demo/class_inheritance_example.py", line 41, inenter C d.use_data()leave C File "/Users/apple/mygit/kd/demo/class_inheritance_example.py", line 34, in use_data data = self.get_data(D="value D") File "/Users/apple/mygit/kd/demo/class_inheritance_example.py", line 28, in get_data return super(C, self).get_data(**kwargs)TypeError: must be type, not classobj
这是python继承问题,通过问度娘,找到好多文章,这里按自己的方式记录整理,以备后续使用。
python实现继承的方法
python可以采用两种方法实现继承。
方法1:使用父类名,例:
class A: def __init__(self): print "enter A" print "leave A" class B(A): def __init__(self): print "enter B" A.__init__(self) print "leave B"
方法2,使用super,例:
class A: def __init__(self): print "enter A" print "leave A" class B(A): def __init__(self): print "enter B" super(C,self).__init__() print "leave B"
方法1是python2.2之前的版本实现继承采用的方法。该方法的问题在于如果有多个继承,当父类更改名字时,所有的子类都要进行相应修改。因此,python2.2之后的版本使用方法2实现继承。
super
super是MRO中的一个类。MRO全称Method Resolution Order,代表类的继承顺序。
关于super,需要注意的一点是它是一个访问排序器,而不是父类。
计划2017年8月底之前翻译完成对super讲解最透彻的一篇文章是Raymond Hettinger的一篇文章。