本文讲解了继承、super关键字、重写、多重继承、类、实例和其他对象的内建函数、私有化等内容。
继承
继承描述了基类的属性如何“遗传”给派生类。一个子类可以继承它的基类的任何属性,不管是数据属性还是方法。
创建子类的语法看起来与普通(新式)类没有区别,一个类名,后跟一个或多个需要从其中派生的父类:
继承
python的子类继承父类后,会把父类的所有的方法,包括构造器init()也继承下来.
init Parent class instance
call parent func
super关键字
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,
会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
super继承只能用于新式类,用于经典类时就会报错。
新式类:继承链开始于object类
经典类:父类没有继承object类,如果此时调用super就会出现错误:『super() argument 1 must be type, not classobj』
示例
phone is: 123456
address is: abcd
data is: 100
重写:子类只要重新定义一个与父类的方法同名的方法,就可以重写覆盖父类的方法。
init Child class instance
call Child func
多重继承
同 C++ 一样,Python 允许子类继承多个基类。但一般不推荐用多重继承。
经典类的多重继承
A.__init__ is called!
因为按照深度优先搜索,所以调用的是类A的构造方法。
新式类的多重继承
运行结果:
C.__init__ is called!
因为按照广度优先搜索,所以调用的是类C的构造方法。
类、实例和其他对象的内建函数
issubclass()
布尔函数 判断一个类是另一个类的子类或子孙类。
hasattr():它的作用是判断一个对象是否有一个特定的属性,一般用于访问某属性前先作一下检查。
getattr()和setattr() :这2个函数分别是获得和赋值给对象的属性,
delattr() :删除特定的属性
child has data attr? True
child.data= 100
delete data attr of child
child has data attr? False
set data attr to 200 for child
child has data attr? True
child.data= 200
私有化
Python没有像Java那样实现真正的封装,只是用双划线和单划线实现私有化.
双划线:防止外部访问.如在func前加双划线,可以防止实例(包括子类的实例)的访问.
A.__func is called!
A.__func is called!
单划线:防止模块的属性用“from mymodule import *”来加载。
在同一个python package中新建2个python文件:kk.py和test_kk.py
kk.py文件:
func is called!
python
python
也修改test_kk.py文件的内容如下:
func is called!
python
python
综上所述:用单划线私有化的模块属性 无法用“from mymodule import *”来加载,可以用其它两种加载方式。。。
继承
继承描述了基类的属性如何“遗传”给派生类。一个子类可以继承它的基类的任何属性,不管是数据属性还是方法。
创建子类的语法看起来与普通(新式)类没有区别,一个类名,后跟一个或多个需要从其中派生的父类:
示例:
class Parent(object): #定义父类
def parentMethod(self):
print 'calling parent method'
class Child(Parent): # 定义子类
def childMethod(self):
print 'calling child method'
p=Parent()
c=Child()
p.parentMethod()
c.childMethod()
继承与覆盖
继承
python的子类继承父类后,会把父类的所有的方法,包括构造器init()也继承下来.
class Parent():
def __init__(self):
print "init Parent class instance"
def func(self):
print "call parent func"
class Child(Parent):
pass
child = Child()#由于Child类没有定义自己的__init__方法,因此,此处调用的是父类的__init__方法
child.func()#同理,子类没有定义自己的func方法,此处调用的是父类的func方法
运行结果:
init Parent class instance
call parent func
super关键字
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,
会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
super继承只能用于新式类,用于经典类时就会报错。
新式类:继承链开始于object类
经典类:父类没有继承object类,如果此时调用super就会出现错误:『super() argument 1 must be type, not classobj』
示例
class Parent(object):#新式类
def __init__(self):
self.phone = '123456'
self.address = 'abcd'
class Child(Parent):
def __init__(self):
#Parent.__init__(self)#采用这种方式调用父类的构造函数不要求继承链开始于object类
super(Child, self).__init__()#super方法要求继承链开始于object类
self.data = 100
def main():
child = Child()
print "phone is:", child.phone
print "address is:", child.address
print "data is:", child.data
if __name__ == '__main__':
main()
运行结果:
phone is: 123456
address is: abcd
data is: 100
重写:子类只要重新定义一个与父类的方法同名的方法,就可以重写覆盖父类的方法。
class Parent():
def __init__(self):
print "init Parent class instance"
def func(self):
print "call parent func"
class Child(Parent):
def __init__(self):#重写__init__方法
print "init Child class instance"
def func(self):#重写func方法
print 'call Child func'
child = Child()
child.func()
运行结果:
init Child class instance
call Child func
多重继承
同 C++ 一样,Python 允许子类继承多个基类。但一般不推荐用多重继承。
经典类的多重继承
class A():#经典类:继承链没有开始于object类,搜索时按照 深度优先 搜索方式
def __init__(self):
print "A.__init__ is called!"
class B(A):
pass
class C(A):
def __init__(self):
print 'C.__init__ is called!'
class D(B,C):
pass
d=D()
运行结果:
A.__init__ is called!
因为按照深度优先搜索,所以调用的是类A的构造方法。
新式类的多重继承
class A(object):#新式类:继承链开始于object类,搜索时按照 广度优先 搜索方式
def __init__(self):
print "A.__init__ is called!"
class B(A):
pass
class C(A):
def __init__(self):
print 'C.__init__ is called!'
class D(B,C):
pass
d=D()
运行结果:
C.__init__ is called!
因为按照广度优先搜索,所以调用的是类C的构造方法。
类、实例和其他对象的内建函数
issubclass()
布尔函数 判断一个类是另一个类的子类或子孙类。
class A(object):
pass
class B(A):
pass
class C(B):
pass
print issubclass(A,object) # True
print issubclass(C,object) # True
print issubclass(B,A) # True
print issubclass(C,B) # True
print issubclass(C,B) # True
attr()系列函数
hasattr():它的作用是判断一个对象是否有一个特定的属性,一般用于访问某属性前先作一下检查。
getattr()和setattr() :这2个函数分别是获得和赋值给对象的属性,
delattr() :删除特定的属性
class Parent(object):
pass
class Child(Parent):
def __init__(self):
self.data = 100
child = Child()
print "child has data attr?", hasattr(child, 'data')
print 'child.data=',child.data
print "delete data attr of child"
delattr(child, 'data')
print "child has data attr?", hasattr(child, 'data')
# print 'child.data=',child.data #已经将data属性删除,因此报错:AttributeError
print "set data attr to 200 for child"
setattr(child, 'data', 200)
print 'child has data attr?',hasattr(child,'data')
print "child.data=", getattr(child, 'data')
运行结果:
child has data attr? True
child.data= 100
delete data attr of child
child has data attr? False
set data attr to 200 for child
child has data attr? True
child.data= 200
私有化
Python没有像Java那样实现真正的封装,只是用双划线和单划线实现私有化.
双划线:防止外部访问.如在func前加双划线,可以防止实例(包括子类的实例)的访问.
class A():
def __func(self):#私有方法:外界(实例以及子类的实例)不可调用
print 'A.__func is called!'
def func(self):
self.__func()
class B(A):
pass
a=A()
#a.__func() #私有方法,外界不可访问 :AttributeError
a.func() # 先调用公有方法func,通过公有方法去调用私有方法__func
b=B()
#b.__func() #私有方法,外界不可访问 :AttributeError
b.func() # 先调用公有方法func,通过公有方法去调用私有方法__func
运行结果:
A.__func is called!
A.__func is called!
单划线:防止模块的属性用“from mymodule import *”来加载。
在同一个python package中新建2个python文件:kk.py和test_kk.py
kk.py文件:
class _A():
def __init__(self,name):
self.name=name
def _func():
print 'func is called!'
test_kk.py文件的内容:
from kk import * #这种方式无法加载 用单划线私有化的模块属性
_func() #NameError: name '_func' is not defined
a=_A('python') #NameError: name '_A' is not defined
print a.name
print getattr(a,'name')
修改test_kk.py文件的内容:
from kk import _func,_A #可以通过这种方式导入 用单划线私有化的模块属性
_func()
a=_A('python')
print a.name
print getattr(a,'name')
运行结果:
func is called!
python
python
也修改test_kk.py文件的内容如下:
import kk #也可以通过这种方式 导入 用单划线私有化的模块属性
kk._func()
a=kk._A('python')
print a.name
print getattr(a,'name')
运行结果:
func is called!
python
python
综上所述:用单划线私有化的模块属性 无法用“from mymodule import *”来加载,可以用其它两种加载方式。。。
原文链接:点击打开链接