简介
继承描述了基类的属性如何”遗传“给派生类,一个子类可以继承他基类的任何属性,不管是数据属性还是方法
简单的继承
class P(object):
pass
class C(P):
pass
c=C()
print c.__class__ #<class '__main__.C'> 类名为C
print C.__bases__ #(<class '__main__.P'>,) 继承自父类P 列出其父类的元组
我们添加一些属性
class P(object):
"P class"
def __init__(self):
print "created an instance of",self.__class__.__name__
class C(P):
pass
#先是父类
p=P() #created an instance of P
print p.__class__ #<class '__main__.P'>
print P.__bases__ #(<type 'object'>,)
print P.__doc__ #P class
print '*********************'
#再是子类
c=C() #created an instance of C
print c.__class__ #<class '__main__.C'>
print C.__bases__ #(<class '__main__.P'>,)
print C.__doc__ #None
通过继承覆盖方法
class P(object):
def foo(self):
print "this is P class"
p=P()
p.foo() #this is P class
#创建子类
class C(P):
def foo(self):
print 'this is C class'
c=C()
c.foo() #this is C class
C继承了P的foo方法,但是C又重写了这个方法将原来父类的方法覆盖了,覆盖的原因之一就是:子类可能需要这个方法具有特定的方法和功能,那覆盖之后,我们还能访问父类的方法吗,当然能
#调用父类的非绑定方法
P.foo(c) #this is P class
#针对这种情况我们可以在继承的过程中显式地调用基类方法
class C(P):
def foo(self):
P.foo(self)
print "this is C class"
c=C()
c.foo()
"""
结果:
this is P class
this is C class
"""
我们注意到这个非绑定方法显示的传递了self,有一个更好的办法就是用super()内建方法
class C(P):
def foo(self):
super(C,self).foo() #super不但能找到基类方法,而且还能为我们传递self
print "this is C class"
c=C()
c.foo()
"""
结果:
this is P class
this is C class
"""
从标准类型派生
不可变类型
比如int float string等不可变类型
class RoundFloat(float):
def __new__(cls, vla):
return float.__new__(cls,round(vla,2))
我们覆盖了__new__
方法来制定我们的对象,使之与标准浮点型有一些区别,我们是通过调用父类的构造器来创建真实的对象
r=RoundFloat(1.34567)
print r #1.35
运用super方法
class RoundFloat(float):
def __new__(cls,val):
return super(RoundFloat,cls).__new__(cls,round(val,2))
r=RoundFloat(1.3434)
print r #1.34
可变类型的例子
比如字典,列表
class SortedKyes(dict):
"重写了keys方法,让他返回排序后的键"
def keys(self):
return sorted(super(SortedKyes,self).keys())
#or sorted(self.keys()) 这个应该好理解一点
d={'k1':'v1','k3':'v3','k0':'v0'}
print SortedKyes(d).keys() #['k0', 'k1', 'k3']
经典类与新式类(python2.7)
经典类
深度优先,从左至右
class P1:
def foo(self):
print "this is P1-foo()"
class P2:
def foo(self):
print "this is P2-f00()"
def bar(self):
print "this is P2-bar()"
class C(P1,P2):
pass
class D(P1,P2):
def bar(self):
print "this is D-bar()"
class G(C,D):
pass
g=G()
g.foo() #解释顺序 G->C->P1
"this is P1-foo()"
g.bar() #解释顺序 G->C->P1->P2
"this is P2-bar()"
当调用foo()时,他首先在当前类G中查找,如果没有找到,就向上查找最亲的父类C, 如果还没有找到,那么继续沿树查找父类P1。
同样对于bar()来说,他通过搜索G,C,P1然后在P2中找到,因为使用这种解释顺序的缘故,D.bar()根本就不会被搜索到。
新式类
广度优先
class P1(object):
def foo(self):
print "this is P1-foo()"
class P2(object):
def foo(self):
print "this is P2-f00()"
def bar(self):
print "this is P2-bar()"
class C(P1,P2):
pass
class D(P1,P2):
def bar(self):
print "this is D-bar()"
class G(C,D):
pass
g=G()
g.foo() #解释顺序 G->C->D->P1
"this is P1-foo()"
g.bar() #解释顺序 G->C->D
"this is D-bar()"
这个是首先查找同胞兄弟,当查找foo时,他检查G,然后是C和D,然后在P1中找到。如果P1中没有,查找会到达P2.
对于bar(),它搜索G和C,紧接着在D中找到了。这样就不会在继续搜索到祖父P1和P2。