Python面向对象之类的封装、继承与多态

简介:

 Python面向对象中类的三大特性,即封装、继承与多态,同时也是所有语言在面向对象编程中的重要特性,下面用实际的代码部分针对每一种特性做出说明。

一、封装

  顾名思义,封装即把我们想要的内容封装到某个地方,因此在这里记录两个问题,一是如何封装、二是如何调用封装的内容。

1、封装数据

1
2
3
4
5
6
7
8
9
class  Company:
     def  __init__( self , dept, leader):
         self .dept  =  dept
         self .leader  =  leader
         
if  __name__  = =  "__main__" :    
     # 将公司名和Leader分别封装到对象obj1、obj2中self的dept和leader属性中
     obj1  =  Company( "A" , "Kevin" )    
     obj2  =  Company( "B" , "Jone" )

2、调用数据

  调用数据又可以分为两种方式:通过对象直接调用、通过self间接调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class  Company:
     def  __init__( self , dept, leader):
         self .dept  =  dept
         self .leader  =  leader    
         
     def  show( self ):
         print  self .dept        
         print  self .leader
         
if  __name__  = =  "__main__" :
     obj1  =  Company( "A" , "Kevin" )    
     obj2  =  Company( "B" , "Jone" )
     
     # 通过对象直接调用封装的数据 
     print  obj1.dept    
     print  obj1.leader    
     
     # 通过self来间接调用,self即为对象本身
     obj1.show()
     obj2.show()

  总结封装特性:即通过类的构造方法将我们想要的内容封装到对象中,调用时通过对象直接调用、或通过self指向的类对象来间接调用。

二、继承

  顾名思义继承即为拥有了某些不属于自己的东西,Python当中类的继承同样如此,通过继承可以为我们的类扩展更多的功能,同时在代码模块化开发、升级的过程中,继承也是一种规模化、高效化的生产方式。

  不同于其他语言,Python中的类还具有多继承的特性,即可以有多个父类,下面通过代码来展示类的单继承、多继承以及继承过程中类成员方法的寻找顺序。

1、单继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class  Scale:
     def  check( self ):
         if  self .count_person >  500 :            
             print  "%s is big company."  % self .name        
         else :            
             print  "%s is small company."  % self .name
             
class  Company(Scale):
     def  __init__( self , name, count):
         self .name  =  name
         self .count_person  =  count
         
if  __name__  = =  "__main__" :
     my_company  =  Company( "ABC" 800 )    
     # Company类中并没有check方法,代码会向上自动检测父类中是否存在check方法,结果在Scale类中找到了
     my_company.check()


2、多继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class  Scale:
     def  check( self ):
         if  self .count_person >  500 :            
             return  "%s is big company."  % self .name        
         else :            
             return  "%s is small company."  % self .name
             
class  Detail:
     def  show( self , scale):
         print  "%s, This company has %s persons."  % (scale,  self .count_person)
         
class  Company(Scale, Detail):
     def  __init__( self , name, count):
         self .name  =  name
         self .count_person  =  count
         
if  __name__  = =  "__main__" :
     my_company  =  Company( "ABC" 800 )
     company_scale  =  my_company.check()
     my_company.show(company_scale)

  上述代码中Company分别继承了父类Scale、Detail,在实例化对象my_company后,我们分别用到了父类中的check和show方法。

3、类的继承顺序

  与其说类的继承顺序,不如说是对象执行方法时,该方法在类中的查找顺序,之所以用到继承,那么一定是需要用到父类当中的某个方法,那么这个方法在类中就要遵循一定的查找顺序,简而言之可以概括为:先下后上、从左到右,下面通过代码来进行说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class  Scale:
     def  check( self ):
         if  self .count_person >  500 :            
             print  "%s is big company."  % self .name        
         else :            
             print  "%s is small company."  % self .name
             
class  Detail:
     def  show( self , scale):
         print  "%s, This company has %s persons."  % (scale,  self .count_person)
         
class  Company(Scale, Detail):
     def  __init__( self , name, count):
         self .name  =  name
         self .count_person  =  count    
         
     def  show( self ):
         print  "This is display from class Company, our company has %s persons."  % self .count_person
         
if  __name__  = =  "__main__" :
     my_company  =  Company( "ABC" 800 )
     my_company.check()
     my_company.show()

1) 创建实例化对象 my_company,并封装了公司名称、人数等基本内容到对象中。
2) 调用类中的check方法,此时程序发现本类中没有check方法,于是开始向上寻找,最终在Detail类中找到。
3) 调用类中的show方法,此时程序发现本类中存在show方法,直接调用。

下面来看稍微复杂些的情况,父类又继承父类,同时一个父类被多个子类同时继承,关系如下图所示。

wKiom1d8ZomQ3yqiAAAjpT-5oi4705.png-wh_50

C_5类继承了C_3和C_4类,同时C_3类、C_4类又分别继承C_1类和C_2类,C_1、C_2类又共同继承了C_0类,我们来看通过对象来调用C_5类中的special方法时,该方法在类中是按照什么顺序查找的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class  C_0:
     def  special( self ):
         print  "I am special from C_0"
         
class  C_1(C_0):
     def  f1( self ):
         pass
         
class  C_2(C_0):
     def  special( self ):
         print  'I am special from C_2'
         
class  C_3(C_1):
     def  f3( self ):
         pass
         
class  C_4(C_2):
     def  f4( self ):
         pass
         
class  C_5(C_3, C_4):
     def  f5( self ):
         pass
         
if  __name__  = =  "__main__" :
     obj  =  C_5()
     obj.special()

  代码最终打印了“I am special from C_0”,由此可见代码是从左边开始查找,一直找到了最顶层的C_0的special方法,但在Python3版本中,同样的情况,代码走到C_1时就会停止向上查找,而是回到C_5中继续向右查找,最终执行了C_2类中的special方法,打印了“I am special from C_2”,这是两个版本中的一点区别。

最后来看一种更为复杂的继承关系

wKiom1d8ZpbwJZqbAABjAyyaLyw227.png-wh_50

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class  C_1:
     def  show( self ):
         self .detail() 
         
class  C_2(C_1):
     def  __init__( self ):
         self .title  =  "This is C_2"
  
     def  show( self ):
         self .detail() 
         
     def  detail( self ):
         print  'I am detail from C_2'
         
class  C_3(C_2):
     def  __init__( self ):
         self .title  =  "This is C_3"
         
class  C_4():
     def  detail( self ):
         print  'I am detail from C_4'
         
class  C_5(C_4, C_3):
     pass
     
my_data  =  C_5()
my_data.show() print  my_data.title

这里我们讨论两个内容:
1、对象my_data中的show方法最终打印了什么内容。
2、对象my_data中的title属性中的内容是什么。

我们来分析一下整个对象实例化及其方法的调用过程
1、创建对象my_data,注意此处的C_5后面是加括号的,即创建实例化对象,此时代码按照从下到上、从左到右的顺序查找构造方法。
2、最终在C_3类中找到了__init__构造方法,并执行其中的对象属性赋值。
3、调用对象my_data中的show方法,此时代码依然按照下至上,左至右的顺序查找整个类中的show方法。
4、最终在最顶层的C_1类中找到了show方法,并执行其中的start方法。
5、代码继续从self所指的my_data对象中重新开始查找start方法。
6、从C_5中查找start方法,未找到--->C_4中,未找到--->C_3中,未找到--->C_2中,找到start方法,并执行其中的detail方法。
7、代码继续从self所指的my_data对象中重新开始查找detail方法。
8、从C_5中查找detail方法,未找到--->C_4中,找到了detail方法,并打印“I am detail from C_4”
9、由于实例化类的时候,代码自动执行了C_3中的构造方法,说以title的值为“This is C_3”

最终结果为:
I am detail from C_4
This is C_3

  总结:在类的继承中我们一直讨论从下至上,从左到右的顺序来查找对应的方法,但实际情况中,父类往往又调用了其他子类当中的方法,此时就要注意self本身的含义,self即指该类实例化对象本身,类中如果调用了self对应的方法,也就是要从对象最底层重新开始寻找对应的方法,例如上述代码中,不能误以为最终C_2中的show方法调用本类里的detail方法,要注意detail方法是要被重新查找的。理解这一点至关重要,否则我们在阅读Python项目的源码时会遇到很多困难。

三、多态

  Python当中的多态我认为是非常好理解的,顾名思义多态就是多种形态,在python中我们在对函数、或是类进行传参的时候,我们往往不会特别关心传递的参数到底是什么类型,例如它可以是字符串、可以是整型、列表、字典、甚至是任何对象,但是在其他编程语言中,参数往往需要被明确定义是什么类型,这也是Python与其他语言的区别吧。




     本文转自阿布ve 51CTO博客,原文链接:http://blog.51cto.com/abuve/1796166,如需转载请自行联系原作者




相关文章
|
1天前
|
Python
Python中的面向对象
【5月更文挑战第4天】面向对象编程(OOP)是Python的核心,涉及类与对象、封装、继承和多态。类是对象的模板,对象则是类的实例。例如,`Person`类有`__init__`构造方法和`greet`方法。
15 3
|
1天前
|
算法 Python
Python面向对象oop编程(二)
Python面向对象oop编程(二)
|
1天前
|
Python
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
|
1天前
|
数据安全/隐私保护 Python
python基础之面向对象
面向对象编程(OOP)是一种以对象为中心的编程范式,通过对象和类实现现实世界的抽象。对象是程序的基本单元,类是对象的模板。主要特点包括:封装,通过访问修饰符隐藏对象内部细节,保证数据安全;继承,子类继承父类属性和方法,实现代码复用;多态,同方法调用在不同对象上产生不同行为,增强灵活性。示例代码展示了Python中的类定义、封装、继承和多态概念。
|
1天前
|
Python
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
62 0
|
1天前
|
Java 程序员 Python
python学习13-面向对象的三大特征、特殊方法和特殊属性、类的浅拷贝和深拷贝
python学习13-面向对象的三大特征、特殊方法和特殊属性、类的浅拷贝和深拷贝
|
1天前
|
开发者 Python
「Python系列」Python面向对象
Python 是一种面向对象的编程语言,它提供了类和对象的概念来组织和封装代码。面向对象编程(Object-Oriented Programming,简称 OOP)是一种编程范式,它使用“对象”来设计软件和应用程序。对象是由数据和可以对这些数据执行的操作(即方法)组成的实体。
23 5
|
1天前
|
Python
python基础篇:python面向对象有哪些魔术方法?具体有什么用?
python基础篇:python面向对象有哪些魔术方法?具体有什么用?
18 1
|
1天前
|
Python
python使用tkinter库,封装操作excel为GUI程序
python使用tkinter库,封装操作excel为GUI程序
255 0
|
1天前
|
Python
Python面向对象(九)
Python面向对象(九)
18 0
Python面向对象(九)