目录
一.引言
1.面向过程介绍
(1)什么是面向过程
面向过程的核心在于“过程”二字
- 过程的终极奥义就是将程序“流程化”
- 过程是“流水线”,用来分步骤解决问题的
- 过程指的是解决问题的步骤,即先干什么再干什么......
- 面向过程的设计就好比精心设计好一条流水线,是一种机械化的思维方式
(2).面向过程的优点
- 复杂问题流程化,进而简单化(一个复杂的问题,分成一个个小的步骤去实现,实现小的步骤会简单化)
(3).面向对象的缺点
一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即便是能,也得是大改,牵一发而动全身
2.什么是面向对象
(1)面向对象介绍
面向过程,核心在于“对象”二字
- 对象的终极奥义就是将程序“整合”
- 对象就是“容器”,用来盛放数据与功能
面向对象理解文字版:
面向对象就相当于上帝,在上帝的视角,人是对象,动物是对象,石头是对象,水是对象,山是对象.....存在的可以扩充,不存咋的可以创造。
面向对象设计理解文字版:
面向对象的设计就好比我们要设计一个小校园模拟器,我们需要在校园中创造各种生活场景,包括上课、做饭、打球等等。这些场景对应的角色就是对象,比如老师、学生、运动员、厨师等。
而每一个角色都会对应其具有的责任和功能
比如一个学生具有姓名、年龄、性别、所在班级等。
学生还有能做的活动,读书、写作、跑步、打篮球等。
比如一个老师可以教书、批改作业等。
比如运行员可以参加训练和比赛等。
当我们的角色和功能构建好以后,我们又需要创建几个学生、一些老师和运行员,让他们进行各项活动。
比如一个学生可以上课、写作业、运动;
比如一个老师可以教课、批改作业;
比如一个运动员可以训练、参加比赛
(2)面向对象的优点
- 解决了程序的扩展性
- 对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中的一个人物参数的特征和技能修改都很容易
(3)面向对象的缺点
- 编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序,极易出现过度设计的问题
- 一些扩展性要求低的场景使用面向对象会徒增编程难度,比如管理linux系统的shell脚本就不适合用面向对象去设计,面向过程反而更加适合
- 无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法准确地预测最终结果
- 于是我们经常看到对战类游戏,新增一个游戏人物,在对战的过程中极易出现阴霸的技能,一刀砍死3个人,这种情况是无法准确预知的,只有对象之间交互才能准确地知道最终结果
3.什么是程序
程序 = 数据 + 功能
编写程序的本质就是定义一系列的数据,然后定义出一系列的功能来对数据进行操作
4.小结
- 在了解了对象的基本概念之后,理解面向对象的编程方式就相对简单很多了,面向对象编程就是要造出一个个的对象,把原本分散开的相关数据与功能整合到一个个的对象里,这么做既方便使用,也可以提高程序的解耦合程度,进而提升了程序的可扩展性(需要强调的是,软件质量属性包含很多方面,面向对象解决的仅仅只是扩展性问题)
二.类与对象
1.引言
- 类即类别/种类,是面向对象分析和设计的基石,如果多个对象有相似的数据与功能,那么该多个数据就属于同一种类
- 有了类的好处是:
- 我们可以把同一种类相同的数据与功能存放到类里,而无需每个对象都重复存一份,这样每个对象只需存自己独有的数据即可,极大的节省了空间
- 所以,如果说对象是用来存放数据与功能的容器,那么类则是用来存放多个对象相同的数据与功能的容器
- 综上所述,虽然我们是先介绍对象后介绍类,但是需要强调的是:
- 在程序中,必需要事先定义类,然后再调用类产生对象(调用类拿到的返回值就是对象)
- 产生对象的类与对象之间存在关联,这种关联指的是:对象可以访问到类中共有的数据与功能
- 所以类中的内容仍然是属于对象的,类只不过是一种节省空间,减少代码冗余的机制
- 面向对象编程最终的核心仍然是去使用对象
(1)什么是类
- 类即类别,种类,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体
- 所以,先有鸡和现有蛋的问题就出来了
- 先有的一个个具体存在的对象(比如一个具体存在的人)
- 还是先有的人类这个概念,这个问题需要分两种情况去看
在现实世界中:先有对象,再有类 世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念 也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在
在程序中:务必保证先定义类,后产生对象 这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类 不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象
三.面向对象编程
1.案例驱动 - 类的定义与实例化
- 按照上述的理论来定义一个类
我们构建一个学校:先先有对象,后有类
# 学生1:
数据:
学校=清华大学
姓名=李建刚
性别=男
年龄=28
功能:
选课# 学生2:
数据:
学校=清华大学
姓名=王大力
性别=女
年龄=18
功能:
选课# 学生3:
数据:
学校=清华大学
姓名=牛嗷嗷
性别=男
年龄=38
功能:
选课
我们可以总结出一个学生类,用来存放学生们相同的数据与功能
# 学生类
相同的特征:
学校=清华大学
相同的功能:
选课
基于上述分析的结果,我们接下来需要做的就是在程序中定义出类,然后调用类产生对象
class Student: # 类的命名应该使用“驼峰体”
school='清华大学' # 数据
def choose(self): # 功能
print('%s is choosing a course' %self.name)
类体最常见的是变量的定义和函数的定义,但其实类体可以包含任意Python代码,类体的代码在类定义阶段就会执行,因而会产生新的名称空间用来存放类中定义的名字,可以打印Student.__dict__来查看类这个容器内盛放的东西
>>> print(Student.__dict__)
{..., 'school': '清华大学', 'choose': <function Student.choose at 0x1018a2950>, ...}
调用类的过程称为将类实例化,拿到的返回值就是程序中的对象,或称为一个实例
>>> stu1=Student() # 每实例化一次Student类就得到一个学生对象
>>> stu2=Student()
>>> stu3=Student()
如此stu1、stu2、stu3全都一样了(只有类中共有的内容,而没有各自独有的数据),想在实例化的过程中就为三位学生定制各自独有的数据:姓名,性别,年龄,需要我们在类内部新增一个__init__方法,如下
class Student:
school='清华大学'
#该方法会在对象产生之后自动执行,专门为对象进行初始化操作,可以有任意代码,但一定不能返回非None的值
def __init__(self,name,sex,age):
self.name=name
self.sex=sex
self.age=age
def choose(self):
print('%s is choosing a course' %self.name)
然后我们重新实例出三位学生
>>> stu1=Student('李建刚','男',28)
>>> stu2=Student('王大力','女',18)
>>> stu3=Student('牛嗷嗷','男',38)
单拿stu1的产生过程来分析,调用类会先产生一个空对象stu1,然后将stu1连同调用类时括号内的参数一起传给Student.__init__(stu1,’李建刚’,’男’,28)
def __init__(self, name, sex, age):
self.name = name # stu1.name = '李建刚'
self.sex = sex # stu1.sex = '男'
self.age = age # stu1.age = 28
会产生对象的名称空间,同样可以用__dict__查看
>>> stu1.__dict__
{'name': '李建刚', 'sex': '男', 'age': 28}