当前课程知识点:计算思维与人工智能基础 > 第三部分:python基础 > 第六章:函数、模块与面向对象 > 6.2面向对象
下面我们给大家介绍一下面向对象编程
什么是面向对象呢
与之对应的一个概念就是面向过程
面向过程的编程是把编程当做一件事情
需要按步骤一步一步的完成的过程
面向对象的是将编程当成一个事物
相当于一个整体的东西
对外界来说事物是直接使用的
不用去管它内部的具体的情况
从构成结构上看
对象是程序的基本单元
也是程序和数据封装的结果
从而能够提高软件的重用性
灵活性和扩展性
我们来看下面这段代码
这是我们要做一件事情就是我们要去拖地
那我们按面向过程的编程的思路的话
我们要分三步
我们取拖把来拖地
然后拖完放回原处
那么如果用Python编程的话
我们就可以用用三个函数来去写他
然后再调用这三个步骤
这就是面向过程的思路
那我们如果用面向对象的思路去完成这件事情
怎么样去做呢
我们可以把它看成是一个整体的事物
所以我们需要定义一个类啊
需要定一个拖地这样的一个类
那我们里面的可以给他初始化
然后呢里面会有一个方法定义怎么样去拖地这样的一个过程
那么在使用的时候呢
我们只要什么把这个类实例化
然后调用里面拖地这个方法
然后他就是把我们三个过程组合在一起
那我们不必要关心它的内部
我们只要去会使用拖地就可以了
那么在面向对象里面
最主要的一个概念是类的概念
那类的定义呢
是通过class加我们的类的名称
后面跟冒号
那后面的就是我们的类的结构体
类是什么呢
类是用来描述具有相同的属性和方法的对象的集合
它定义了该集合中每个对象所共有的属性和方法
那么说这就是我们这个类里面的属性
那么下面呢
def开头呢
这就是我们的方法
那属性是也称之为我们的类变量
在整个实例化的对象中是公用的
那么类变量就是定义在我们的函数体的之外
在类中啊是这样子的
他的位置在这个地方
下面就是我们方法的定义
那么方法定义呢
其实呢
就是我们的函数的定义
那么函数里面有函数的名称与我们的参数
那里面的也可以有变量
那么这个变量就是实例变量
那么定义在方法中的这个变量的
只作用于当前实例的类
那我们在定好类以后呢
使用的时候呢
是通过创建一个实例对象
也就是类的实例化来使用的
我们可以看实例化以后赋值给一个变量
我们通过这个变量点后面的方法的名称
来去调用我们类里面的方法
好我们在jupyter下看一下我们这段代码的执行结果
这段代码就是我们前面
这是我们类的定义
那么类的名称
类的属性或者我们的类变量
那我们这里面这是类的方法的定义啊
那我们在使用的时候怎么样使用呢
第一步是要实例化
然后呢类的方法的调用可以通过我们的什么呀
实例化对象点后面跟方法的名称
那还有可以使用它我们类里面的变量
是通过点后面跟属性的名称这样去适应的
我们来看这个执行的结果应该是什么呀
那么这个方法呢
其实就是第一
要要输出他
我们第二个方法要输出他
第三个方法
climb要输出他
那第四个方法是输出run
要去跑步
然后呢
用我们输出了乌龟的颜色和乌龟的有几条腿
那是他的属性的输出
我们来看他的执行结果
这就是函数的结果
后面的这个是我们什么呀
类里面的属性的调用的结果
面向对象的三个特征分别是封装
继承和多态
什么是封装
封装是根据职责将属性和方法封装到一个抽象类中
并且类可以把自己的数据和方法只让可信的类
或者对象操作
Python的列表list其实就是一个对象
它提供了很多的方法
比如说sort
appeng等
封装后就可以直接调用里面的方法
这个时候呢
是需要注意的就是在我们封装的类中
会有公有变量和私有变量
公有的方法和私有的方法
那么在调用中的是有不同的
那我们在jupyter通过一个例子
来说明公有变量私有变量
以及公有方法和私有方法的调用
我们来看在jupyter下这个类的定义
那我们在前面讲过类的定义里面有什么呀
有类变量和函数
也就类的方法的一个定义
那么在Python中私有变量或者是函数呢
只要在他的前面加什么呀下划线
那么这个函数或者是变量就是私有的
我们来看这个类的定义
那么这个类变量就是私有的类变量
那我们在私有的类变量呢
是只能在我们这个类的内部的函数中才能够使用它
所以呢我们可以看到
在下面的这个函数中
对私有变量进行求和赋值
那么公有变量也可以求和赋值
那我们通过print语句呢输出私有变量的值
是这样子的一个过程
那我们这个类定义以后下面要使用的时候呢
第一步进行实例化
然后呢我们可以调用它的方法
也可以调用它里面的公有变量
我们执行一下看他的结果应该是
我们可以看到他方法调用这个方法
那么方法里面呢是输出他的私有变量
也就输出它的值是2
下面一个print语句呢是输出他的公有的变量的值
那么也就是公有变量的值赋值以后他应该是什么
1
我们执行结果以后
他的结果应该是一个2
是通过方法调用的输出的私有变量的值
而1呢是我们输出的公有变量的值
下面我们再看这段代码
我们也是定义了一个类是site这个类
那么这个类里面的有一个方法叫_init_
那么这个是我们的Python里面的构造方法
那么这个构造方法呢
是在实例化这个类的时候呢它会自动执行
那self这个这个参数代表自己
那么name,url是他的一个新参
那么在这个可以这是给他的做了一个赋值
另外我们可以看到
这是一个who是公有的方法的定义
那么输出name和url
url这是一个实例变量
那么这个是私有的实例变量
这个实例变量的可以在定义类的其他的函数中
或者方法中也是可以调用
所以在这个地方只能在内部类的内部去调用它
那下面这个定义了一个_foo
那我们这个foo就是一个私有的方法
那我们这个私有的方法
那么输出他
这个私有的方法的调用也只能是在本类中的函数
那么这个foo函数呢
在里面呢我们可以他是有一个输出语句
然后呢调用了这个私有的方法
是这样的几个函数组成的
这是我们site这个类
那我们看在使用的时候呢
首先我们可以实例化
然后我们通过调用一个公有的方法who和foo
这样的去实现它
他会得到一个什么样的结果呢
那么who出来的会是输出我们的名字
也就是我们输入的两个参数
宁夏大学和信息工程
那么foo呢是要输出什么呀
私有方法
前面print的一个是一个公有方法
然后呢是一个私有方法
那么得到的结果就是我们输出这是我们who的结果
那么这时是我们foo的这个函数的结果
那么这个私有变量也好
我们的私有方法也好
那我们在调用的时候只能在类内部调用
不能实例化以后外部调用
像我们上面这一个
如果print语句直接去调用我们内部的方法的时候
代码是会报错的
同样我们下面这个私有方法
我们这个foo里面呢是内部是可以调用_foo的
如果我们实力的话有直接去调用它的时候呢
他也是会报错
这就是我们在使用公有变量私有变量
以及公有方法和私有方法的区别
面向对象的另外一个特征就是继承
什么是继承呢
继承其实是子类去共享父类之间的数据和方法的这种机制
那么一个子类继承多个父类呢
这样的继承方式
我们把它称之为多继承
也就是一个子类可以有多个父类
那另外一种呢
是一个子类只能有一个父类
那么这样的就是一个单继承的关系
python中支持多继承和单继承
那么继承主要实现代码复用的这个特点
那继承可以使现有类呢无需改变
或者添加代码的情况下
添加扩展其他类的功能或者数据
子类自动共享父类之间数据和方法的一种机制
面向对象的另外一个特征呢
就是多态
不同对象对同一个方法响应不同的行动
增加了程序的灵活性
因而呢就是不同的功能的函数
可以使用相同的函数名
那么同意操作呢
作用于不同的对象
那么可以有不同的解释
产生不同的执行的结果
那么这个呢都是通过继承来实现的
那么原则上如果子类重写了父类的方法
运行的时候呢
只会调用在子类中重写的方法
而不会调用父类的方法
那么多态体现了开闭原则
软件实体呢
就对外扩展是开放的
对内修改是关闭的
这样的一个原则
那么下面呢我们通过几个例子
再看一下我们在代码中如何实现继承和多态的
我们在jupyter下看一下这段代码
那么首先呢我们定一个class People这样的一个类
那类里面的类变量有三个
那么前面两个name,age是我们的公有变量
那么看_weight是一个私有变量
这个前面讲过init函数呢
前面带_后面带_呢是我们一个构造函数
那么是在这个类在实例化的时候
它可以自动执行的
那么这个self就带代表类的本身
那么把这n,a,w这几个变量
分别赋值给我们类里面的变量
name,age和weight
另外一个方法是speak
我们输出这里面的name和age
这是一个类
那么下面看我们这个另外一个class Student
括号里面people指的就是student继承了people后面冒号
那我们可以看下面这个类的定义
那么他有自己的一个类变量是grade
另外的话他也有自己的init方法
init方法它调用了people也叫父类的构造方法
那另外呢给自己的grade赋了值
他有自己的一个方法是speak
那么上面的一个方法也有父类的speak
那么这个是子类的speak
也就是说子类其实重写了父类的一个方法
那么也是一个输出
输出他的name,age多了一个他自己类的grade年级
那么这是一个单继承
那么这是一个子类
那么继承了父类people
那我们在引用的时候我们可以实例化
student的里面我们给他了一个name的值
那么还有里面的student我们要给他一个name的值
还有一个a,w,g
a,w,g
那么这就这几个值给他
那么这个地方调用s.speak
当然他执行的是什么呀
应该是我们子类的这个speak
而他的输出结果就应该是什么呀
是我们说的名字
这个ken说他是十岁
然后他在读几年级啊是这样子的
我们来看这个结果是不是这样子的
我们能运行
ken他几岁
他在读几年级啊
那么这是这个可以看的到我们这个子类
那我们重写了父类调用的时候
我们实现的时候他就是什么
实现子类把它独有的这个方法
那我们再看下面这段代码
我们又定义了一个类class Speaker
那他有自己的topic
name
然后这个一样他的什么样构造方法
它有一个自己的方法叫talk
那么talk他输出的是这个他的talk者的名字
和这个topic把他的题目是什么
我们来看下面这个class Sample
sample括号里面会有speaker和student
说明他有两个什么呀基类或者是两个什么呀父类
那么这里面呢
我们可以看
这是他有自己的一个内变量
然后我们他的初始化
它的初始化是调用父类
student还调用了speaker的初始化
这样的话 我们可以看的到这个sample就是一个什么呀
这是sample的定义
那么这里面呢他只是有一个自己的构造方法
让他继承了父类和speaker,student的构造方法
那我们来看他我实例化以后
那实例化以后
他输出的时候我们可以看到输出test. grade他是他自己的什么呀
test. grade是我们可以看到这个点grade是
grade是我们student里面
刚才我们谈了个父类student里面有一个是吧这样的一个内变量
他是可以调用的
然后呢他又调用了一个什么呀
speak的方法来自speaker
speaker的方法来自student
还有一个什么样啊
talk的方法是来自于什么呀
speaker
我们来可以看到这个他们输出的结果是speak应该是是输出
刚才我们看到这是这段他的说的谁多少岁
然后他是几年级
下面一个方法是调用talk
talk他就应该调用他
他是要要说出它的主题
他的名字和主题
我们执行一下可以看到
这个我们可以看得到
这个是前面这个grade可以调用
因为他是一个在student里面的他是一个内变量
是可以调用父类的变量
那么这是一个test.speak的输出
后面这个是talk的输出
那么有的时候呢
我们一般的情况下呢父类的方法都是不同名的
最好不同
如果是两个同名
比如说这个刚才那个student我们有一个speak
然后呢我们如果是这个speaker里面这个talk也是speaker的话
它调用的时候是这个我们把哪一个写在前面
他就调用什么的
两个方法重复的时候
如果父类方法同名的时候呢
它就调用我们括号前面排在前面的那个方法
这个地方是需要大家注意的一个点
另外我们可以看得到这个方法的一个重写
那么这是一个父类class Parent这是个父类
我们有一个方法就是只有一个myMethod的方法
那么输出了一个
那么如果他是子类的话
还有这个myMethod的方法的时候呢
我们可以对父类进行重写
重写以后呢
在调用的时候
你可以看实例化以后c.myMethod就调用它自己的方法
如果要调用父类的方法时候他可以怎样调用
那么后面我们可以通过super我们这个super是调用它的父类
Child的父类的myMethod就可以调用它
那么子类调用方法是输出这一段啊
那么父类调用方法输出他
那么执行了以后
我们可以看的到他是有什么
前面的是调用子类的方法
那么通过这个print这个一排等号以后下面的是什么呀
那是我们通过子类调用父类的这个方法
那么这是我们那个方法的一个重用啊
下面我们看一下这个多态的例子
那么多态呢是统指事物的多种形态
一个抽象类有多个子类
因而呢多态的概念是依赖于继承的
那么一种调用方式不同的执行的结果
那么就是多态的一个展现的形式
我们来看这个有一个例子
我们来看这个我们定义了一个class Base0bj
那他下面有三个方法
分别是think
say和sleep
简单的输出think
say和sleep
定义一个people我们可以看括号Base0bj就是它继承了Base0bj
并且呢people重写了think say和sleep的方法
又定了一个Dog也是继承Base0bj
也重写了他的think的方法
say的方法
那么sleep方法里面呢
除了重写了以后它还调用了什么呀
子类调用父类的方法
用super
父类就是Base里面.think
这个方法是这样子的
再看下面我们定义了一个Action这样的一个类
他呢初始化后也有自己的方法
每一个方法呢
我们可以看到他进来一个参数obj
那么它的think方法是调用obj.think
那他的say的方法也调obj.say
sleep方法调用obj.sleep
我们看下面呢
我们实例化一个Action
传进来的参数是Dog的时候
我们可以看他在调用的时候
是say think sleep
那么这个调用的时候和下面再实例化一个
引进来一个不同的参数是people
他的调用的方式看来是一样
我们可以看到他的结果呢
那么结果在调用的时候
调用的就是我们看执行结果是什么啊
稍有不同的
那么因为Dog里面的sleep方法又调了父类的think方法
所以他是这样
那么这个呢啊
people里面的是他自己写的方法是这样子
那么这就可以看的到我们同样是用什么呀
一个调用的方式
那么执行的调用的参数不同
执行的结果也是不同的
这个就是我们多态的一个体现
-章测试
-章测试
-第一章:python简介
--章测试
-第二章:编码规范
--2.2常量和变量
--章测试
-第三章:数据类型
--章测试
-第四章:基本运算
--4.2比较运算符
--4.3逻辑运算符
--4.4位运算符
--章测试
-第五章:程序控制结构
--5.1顺序结构
--5.2条件结构
--5.3循环结构
--5.4跳转结构
--5.5异常处理
--章测试
-第六章:函数、模块与面向对象
--6.2面向对象
--6.4模块与包
--章测试
-第七章:文件操作
--7.2文件的写入
--章测试
-第八章:python生态库
--章测试
-第九章:TensorFlow基础
--章测试
-第十章:实例分析与实践
--章测试
-第十一章:人工智能在自然语言中的应用
--章测试