为什么要面向对象编程?
伟大的领袖毛泽东曾说过:编程最大的敌人是重复。
- 最开始,在程序中写的一条条语句,在执行的时候会变成一条条指令交给CPU执行。这就是**“程序是指令的集合”** 。
- 为了简化程序的设计,引入了函数的概念。把相对独立、经常重复使用的代码放到函数中。当一个函数的语句过多的时候,我们就给它拆分成一个个子函数。函数式编程
- 单当程序到极度复杂的时候,单纯的函数无法满足维护、开发、升级的工作。于是有人提出面向对象编程。推翻了以 小块函数为单位的思想,而是把数据+函数组成的对象为最小单位。
什么是面向对象编程?
你肯定听过,面向对象的三大要素:封装、继承和多态。
正式的说法:把一组数据结构和处理他们的方法组成对象 (object
), 把相同行为的对象归纳为类 (class
), 通过类的封装 ( encapsulation
)隐藏内部细节,通过继承 (inheritance
)实现类的特殊化 (specialization
)和 广泛化 (generalization
), 通过多态 (polymorphism
)实现基于对象类型的动态分派。
是不是很难懂?说起来也拗口,没有基础的人根本看不懂。
这样讲吧,我们在出生的时候就被赋予一个类 (人),我们自身有一些属性 (身高,体重 ,年龄),还有一些技能,也就是方法 ( 吃饭 、呼吸 )
- 封装:你今年多少岁了,你只需要告诉别人结果,不用告诉人你是怎么算的,不需要知道内部实现细节。这就是封装。
- 继承:我们之所以有这些属性、技能,是因为我们的父母也是人,我们是遗传基因得来的。
- 多态:一些人演化出来特有技能,比如倒立洗头,泡妹。但有一些人不会。
说了这么多,面向对象是一种思想,范式,约定。你也可以不这么做,也能写代码,只是可能,当应用复杂到一定程度,只有你看的懂,无法同其他人交流。
面向过程与面向对象对比
假设我们要处理学生的成绩表,打印一个学生的成绩: 姓名 + 分数
,面向过程的程序可以用一个dict表示:
std1 = { 'name': 'Michael', 'score': 98 } std2 = { 'name': 'Bob', 'score': 81 }
函数式编程的思想就是,直接思考程序的执行 , 面向过程
。
def print_score(std): print(f'{std[name]} : {std[score]}')
面向对象的编程思想 ,则首先思考的是 std 应该是一个 学生对象,有 姓名(name) 和 分数 (score) 这两个属性。有一个技能打印成绩 print_score() , 如果要打印成绩需要,先创建一个学生,然后告诉学生我要打印成绩。
class Student(object): def __init__(self, name, score): self.name = name self.score = score def print_score(self): print(f'{std[name]} : {std[score]}')
zhangsan = Student('张三', 59) lisi = Student('李四', 87) zhangsan.print_score() lisi.print_score()
类的定义和实例
下面是一个类
class Student(object): def __init__(self, name, score): self.name = name self.score = score def print_score(self): print(f'{std[name]} : {std[score]}')
__init__
是一个特殊方法用于在创建对象时进行初始化操作 , 为学生对象绑定 name
和 score
两个属性
- 注意:特殊方法“
__init__
”前后分别有两个下划线!!!- 注意到
__init__
方法的第一个参数永远是self
,表示创建的实例本身,因此,在__init__
方法内部,就可以把各种属性绑定到self
,因为self
就指向创建的实例本身。- 如果有了
__init__
方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__
方法匹配的参数,但self
不需要传,Python解释器自己会把实例变量传进去:
def print_score(self)
和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self
,但是调用时,不用传递该参数。