上一篇文章我们简单地介绍了Python函数,包括函数的定义,参数传递等,接下来,我们将继续学习Python中的面向对象编程。
Python在设计之初就是一门面向对象的编程语言,正因为如此,在Python中,一切皆对象。Python的面向对象编程我们将从以下五个方面去介绍:
-
面向对象VS面向过程
-
面向对象简介
-
类和实例
-
面向对象三大特征
-
面向对象重写和重载
Part.1 面向对象 VS 面向过程
我们通常说,C或C++是面向过程的编程语言,JAVA或Python是面向对象的编程语言,那么,什么是面向对象呢?什么又是面向过程呢?他们之间的区别和联系是什么呢?
面向过程编程
在学习面向过程的基础概念之前,我们先通过一个数学表达式来理解面向过程编程的基本思路。
当我们求解数学表达式 2+3-6*2+10 , 怎么去求解这个数学表达式呢?
计算过程
1、乘除法的优先级高于加减法,2*6=12,所以,第一步之后的表达式为,2+3-12+10;
2、加减法的优先级是相同的,从前往后以此计算,2+3=5,表达式变成5-12+10;
3、5-12=-7.表达式变成-7+10;
4、最后计算-7+10=3.
在解题的过程中,我们将表达式的计算分为四步,
首先计算乘法 2*6=12
其次计算加法 2+3 的值
然后计算减法,5-12
最后计算加法,-7+10,结果为3
上述的求解过程就是一个典型的面向过程的编程的解题思路,面向过程就是将问题分解为若干个步骤,然后一步步地进行求解。
面向过程(OO):面向过程程序是由不同的函数组成,最小的程序单元是函数,每个函数负责完成某一个功能,用于接受输入数据,函数对输入数据进行处理,然后输出结果数据,整个软件系统由许多函数组成,其中作为程序入口的函数称之为主函数,主函数依次调用其他函数,普通函数之间可以相互调用,从而实现整个系统功能。
当你拿到一个问题时,你分析这个问题 是第一步先做什么,第二步再做什么,分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现。其特点在于适合简单任务,无需协作。指导思想是:具体问题具体分析。
面向过程的程序=算法+数据结构
面向过程的编程优点在于,
(1)以步骤的形式解决问题,符合人的思考方式,无需考虑复杂的抽象概念
(2)将问题划分为若干个步骤,程序的流程清晰,易于实现
(3)项目不是特别大时,以面向过程的方式设计,会更加高效。
面向过程设计方法很大的不足在于程序的可扩展性,可维护性,因为面向过程是按解决问题的先后步骤来进行设计的,如果产品需求或解决问题的逻辑发生了改变,那这些步骤也需要重新设计。尤其当软件的规模到达一定程度时,这样的问题会更加突出,面向对象设计更好地解决了这类问题。
面向对象编程
上面讲到,面向过程是把问题的求解过程分解为多个步骤,而面向对象关注的是问题本身,把问题抽象成一种数据类型。理解面向对象,需要思考两个核心问题:什么是对象?什么是面向对象?
什么是对象?
在面向对象的程序设计中,将事物抽象成一种数据类型,通常定义为类,类是对于现实世界的抽象,如动物,人等,这是对于现实世界的抽象。对象是对类的具体化,一切皆对象,如山河湖海,日月星辰,天地灵长,飞禽走兽。
什么是面向对象?
面向对象编程的核心是抽象,什么是抽象呢?简单地解释,抽象即概括和归类。在面向对象中,抽象后的数据类型就叫做类,类由类属性和类方法组成。类属性表示的是类的共有特征,而类方法表示类共有的行为。对类进行实例化,可以得到一个具体的对象,实例化后的对象共享类的属性与方法。
面向对象是以功能来划分问题,而不是步骤,以一种组件化的形式进行代码设计。对于某一类问题的解决,一种以对象为基础,以事件或消息来驱动对象执行处理的程序设计技术。它具有抽象性、封装性、继承性及多态性 。面向对象处理问题:将面对的问题抽象处理,以对象为中心封装成不同的类,然后实例化不同的具体对象,利用具体的对象来描述在整个问题的解决中所起到的作用。面向对象编程是面向过程编程的基础上发展来的,它比面向对象编程具有更强的灵活性和扩展性。指导思想是:透过现象看本质。
对象=算法+数据结构
面向对象的程序=N个对象+控制信息
面向对象 vs 面向过程
面向对象和面向过程同为对软件分析设计开发的一种思想,指导人们用不同的思想设计开发软件。
举个栗子: 设计五子棋来理解面向过程与面向对象。
面向过程的设计思路就是首先分析问题的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用不同的方法来实现。
面向对象的设计思路是抽象组成问题的类,整个五子棋可以分为1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。整个游戏的运行过程具体如下:第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。
二者之间的联系
1> 都是解决问题的一种思维方式
2> 简单问题可以使用面向过程的编程思想
3> 复杂问题在宏观层面上使用面向对象编程,在微观层面上使用面向过程编程。
二者之间的区别
用面向过程的方法写出来的程序是一份蛋炒饭,而用面向对象写出来的程序是一份盖浇饭。
蛋炒饭制作把米饭和鸡蛋混在一起炒匀。盖浇饭呢,则是把米饭和盖菜分别做好,你如果要一份红烧肉盖饭呢,就给你烧一份红烧肉;如果要一份青椒土豆盖浇饭,就给烧一份青椒土豆丝。
蛋炒饭的好处就是入味均匀,吃起来香。如果恰巧你不爱吃鸡蛋,只爱吃青菜的话,那只能全部倒掉,重新做一份青菜炒饭了。盖浇饭就没这么多麻烦,你只需要把上面的盖菜拨掉,更换一份盖菜就可以了。盖浇饭的缺点是入味不均,可能没有蛋炒饭那么香。那么从饭馆角度来讲的话,做盖浇饭显然比蛋炒饭更有优势,他可以组合出来任意多的组合,而且不会浪费。
盖浇饭的好处就是”菜”“饭”分离,从而提高了制作盖浇饭的灵活性。饭不满意就换饭,菜不满意换菜。用软件工程的专业术语就是”可维护性“比较好,”饭” 和”菜”的耦合度比较低。蛋炒饭将”蛋”“饭”搅和在一起,想换”蛋”“饭”中任何一种都很困难,耦合度很高,以至于”可维护性”比较差。软件工程追求的目标之一就是可维护性,可维护性主要表现在3个方面:可理解性、可测试性和可修改性。面向对象的好处之一就是显著的改善了软件系统的可维护性。
Part.2 面向对象简介
我们知道,面向对象编程是一种代码封装的方式,通过模拟真实世界中的事物,并将描述特征的数据和代码块封装到一起,打个比方,若在某游戏中设计一个乌龟的角色,应该如何来实现呢?使用面向对象的思想会更简单,可以分为如下两个方面进行描述:
-
从表面特征来描述,例如,绿色的、有 4 条腿、重 10 kg、有外壳等等。
-
从所具有的的行为来描述,例如,它会爬、会吃东西、会睡觉、会将头和四肢缩到壳里,等等。
在面向对象编程过程中,抽象现实世界中的事物为类,并基于这些类创建对象,通过对象之间的相互关系理解代码的运行逻辑。在学习面向对象变成之前,首先需要了解面向对象编程的一些基本术语。
-
类 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。
-
对象 通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
-
方法 类中定义的函数,用于描述事物的行为特征
-
属性 类中定义的变量。
-
成员变量 类变量或者实际变量用于处理类及其对象的相关数据
-
类变量 定义在类中,且在函数体之外,
-
方法重写 如果从父类中继承的方法不能够满足子类的需求,可对其进行改写,
-
局部变量 定义在方法中的变量,只用于当前实例的类
-
实例变量 集一个派生类继承基类的字段和方法
-
实例化 根据类来创建对象称之为实例化
如何去理解上面的这些面向对象的编程术语呢?后面我们会详细介绍面向对象编程的这些术语,在这里,我们通过代码的形式,简单直观地对于Python中面向对象术语有一个直观地理解。
【示例程序一】
# -*- coding: utf-8 -*-
"""
@Time : 2021/8/27 20:25
@Author : LYP
@FileName: pythonOop.py
@SoftWare: PyCharm
"""
class Car(object):
def __init__(self,type,price):
self.type = type
self.price = price
def carinfo(self):
print("type:%s,price:%d"%(self.type,self.price))
tesla = Car('tesla',2000)
jeep = Car('jeep',1000)
tesla.carinfo()
jeep.carinfo()
在上述代码中,定义一个car类,并用初始化方法__init()__,其中包括参数type.price,然后初始化变量,此外定义类中的方法carinfo,在方法中定义函数体,打印车的相关信息。定义好类之后,实例化类创建类的对象 tesla 和 jeep,并输入初始化信息,调用类中的方法,输出实例化类的具体信息。
执行上述代码,运行结果如下。
【示例代码二】
class Role ( object ) :
menbers=0
def __init__ ( self , name , role , weapon , life_value) :
self.name = name
self.role = role
self.weapon = weapon
self.life_value = life_value
Role.menbers += 1
def buy_weapon( self , weapon ) :
print ("%s is buying [%s]" %(self.name,weapon) )
#实例化对象.
p1 = Role ( 'Yard' , 'police' ,"AK47",90 )
r1 = Role ( 'Jack' , 'terrorist' , "B22",100 )
r2 = Role ( 'T2' , 'terrorist' , "B22" ,123)
r3 = Role ( 'Jck' , 'terrorist' , "B22" ,345)
#调用方法
p1.buy_weapon('AK47')
r1.buy_weapon('AK47')
r2.buy_weapon('AK47')
r3.buy_weapon('AK47')
在上面代码中,我们定义了一个角色Role的类,并定义了相应类的属性和方法,在类的方法中,我们打印卖东西的信息。定义好类之后,我们实例化四个对象p1,r1,r2,r3,并依次次调用方法buy_weapon().
上述代码,运行结果如下:
【代码集合】
# -*- coding: utf-8 -*-
"""
@Time : 2021/8/27 20:25
@Author : LYP
@FileName: pythonOop.py
@SoftWare: PyCharm
"""
#示例代码一
class Car(object):
def __init__(self,type,price):
self.type = type
self.price = price
def carinfo(self):
print("type:%s,price:%d"%(self.type,self.price))
tesla = Car('tesla',2000)
jeep = Car('jeep',1000)
tesla.carinfo()
jeep.carinfo()
#示例代码二
class Role ( object ) :
menbers=0
def __init__ ( self , name , role , weapon , life_value) :
self.name = name
self.role = role
self.weapon = weapon
self.life_value = life_value
Role.menbers += 1
def buy_weapon( self , weapon ) :
print ("%s is buying [%s]" %(self.name,weapon) )
#实例化对象.
p1 = Role ( 'Yard' , 'police' ,"AK47",90 )
r1 = Role ( 'Jack' , 'terrorist' , "B22",100 )
r2 = Role ( 'T2' , 'terrorist' , "B22" ,123)
r3 = Role ( 'Jck' , 'terrorist' , "B22" ,345)
#调用方法
p1.buy_weapon('AK47')
r1.buy_weapon('AK47')
r2.buy_weapon('AK47')
r3.buy_weapon('AK47')
运行结果如下:
关注公众号 Python大视界,一起学习动手学python,共同进步,一起成长啦。