当前位置: 首页 > news >正文

六.python面向对象

学过C++或者Java的同学一定了解过面向对象的相关内容,编程语言一般分为两种设计方式:面向对象面向过程,早期的编程语言多是面向过程的,由多个过程组合在一起,而Python在设计的时候就是一种面向对象的语言,因此在Python是面向对象的编程语言。本节我们先来了解一下面向对象编程的概念。

目录

1.基础概念

2.类的定义

2.1. 类的定义

2.2. __init__()方法

2.3. 参数传递

3.类的方法

4.类的继承

5.类的重写

6.类的多态


1.基础概念

1.1. 对象

首先我们要学习一下什么是对象,对象的英文是‘Object’,我们的生活中到处都是对象,你面前的电脑、手中的手机或者是书架上的书等等都是对象,对象是一种实际存在的实体。

我们在学习对象的时候可以把对象看成两个部分,一部分称为属性,一部分称为行为

例如:我们买了一个闹钟,闹钟的材质是它的属性,当闹钟响起来的时候是它的行为。

1.2. 类

我们在前面学习过的数据类型都属于类,类是Python的基本构造,在类中包含很多方法,我们在学习类的时候可以把类理解为一个教室,当我们创建了一个教室的时候,我们规定这个教室需要学习语文、数学和英语,当一个学生加入这个班级,就需要学习这三门科目,类往往是我们定义的一个载体,类中的成员会具有相同的属性和行为。

我们可以把所有汽车看成一个类,也可以把所有飞机看成一个类,类是一种比较抽象的概念,我们在定义的时候要根据实际情况来定义。

面向对象编程有三大特点:封装、继承和多态。

1.3. 封装

关于封装,我们可以举生活中的例子来学习一下,首先我们先从字面意思思考一下,封装就是把东西封了起来,当我们买了一台音响,音箱内部存在电路板、线路等结构,而我们使用者不需要去知道他的内部结构和使用原理,所以这些结构被封闭在箱体内部,在箱体外提供一些接口供我们连接,这些在音箱内部的属于封装起来的东西。

我们在写程序的时候也可以采用封装的理念,对于一些内容我们不提供接口来使用它们,它们属于内部的构造,属于不可变的内容,这种内容即为封装。

1.4. 继承

提到继承,大家一般都会联想到遗产,我们如果拿遗产来形容继承的话,在现实生活中的遗产继承一般是单对单的,如果是单对多的形式,那么多个人获取到的遗产很有可能是不一致的,而我们在程序里的继承是一种完全继承的关系。

我们可以把车看为一个对象,然后不管是奔驰车还是宝马车又或者是大众车,这些车都继承了车的全部属性和行为。我们把车看成一个类,给车定义了在地面驾驶和4个轮胎的属性,那么当宝马车来继承这个类,宝马车就获得了在地面驾驶和4个轮胎的属性,如果我们给车定义了高速行驶的行为,那么宝马车也继承了它高速行驶的行为。

我们在使用继承关系的时候,我们把车称为‘超类’或者‘父类’,而继承而来的宝马车称为‘子类’或者‘派生类’。

1.5. 多态

多态就是一个父类有多个属性,根据这些属性而衍生了多个子类,我们继续拿车来举例,我们可以给车定义两个属性,一个在马路上行驶,一个是在轨道上行驶,而这两种属性又都包括可载人,那么我们在定义子类的继承的时候,就可以定义了两种子类,一种是可载人的但在马路上行驶的汽车,一种是可载人但在轨道上形式的汽车,这种一个类衍生出多个子类,他们有公共属性也有私有属性的方式称为多态。


2.类的定义

2.1. 类的定义

类的定义使用的是class关键字,语法结构如下:

1

2

3

class Name:

    '''类文档'''

    content

Name为我们要创建的类的名字,注意我们在使用的时候尽量采用大写的方式,如果采用两个单词命名,两个单词的首字母都采用大写的方式。

类文档为我们写入的帮助我们理解这个类的信息。

content为类中的类体,包含变量、方法和属性等内容,如果我们在定义类的时候暂时不需要添入内容,可以采用pass语句充当一种占位语句。

我们来定义一个类:

1

2

3

4

5

class School:#这种方式我们就定义了一个名为School的类

    '''定义一个学校类'''    

    pass

school = School()#通过这种方式来调用这个类

print(type(school))#通过输出看一下它的类型print(school)

输出结果为:

1

2

<class '__main__.School'>

<__main__.School object at 0x03372DD8>

通过结果我们可以看到school为一个类,通过第二行我们可以看出school是School类的实例。

2.2. __init__()方法

在创建类的时候,往往会创建一个__init__()方法,这种方法属于构造方法,也就是每次调用这个类都会使用这种方法,参数的传递也是在这个方法里。

这种方法中必须包含一个self参数,也必须是第一个参数,这个参数是指向这个实例本身的,它可以访问这个类中存在的属性和方法。

看下面的实例:

1

2

3

4

5

6

7

class School:#这种方式我们就定义了一个类,如果我们要调用这个类

    '''定义一个学校类'''

    def __init__(self):

        print('这里是__init()__方法')

    def __judge__(self):

        print('判断这个方法是否被调用')

school = School()

输出结果为:

1

这里是__init()__方法

通过输出我们可以看出只要调用了这个类就自动调用了这个__init__方法,而下面的__judge__方法是没有被调用的。

我们还可以通过循环的方式来验证一下是否每次调用这个类就会使用一次init方法:

看下面代码:

1

2

3

4

5

6

7

8

class School:

    '''定义一个学校类'''

    count = 0

    def __init__(self):

        School.count += 1

        print('这里是__init()__方法的第%d次使用'%School.count)

for in range(5):

    School()

输出结果为:

1

2

3

4

5

这里是__init()__方法的第1次使用

这里是__init()__方法的第2次使用

这里是__init()__方法的第3次使用

这里是__init()__方法的第4次使用

这里是__init()__方法的第5次使用

我们可以通过输出结果看出我们使用5次init方法,当我们第一次调用这个类的时候,count为0,然后通过init方法进行加1操作,在init方法里的school.count每次进行加1,然后最外面的count是不变的,通过这个例子我们可以了解到init的使用法发。

2.3. 参数传递

我们在学习函数的时候,参数的传递是定义在函数名内的,而在类中,我们通过init方法可以更方便的进行参数的传递。

看下面的例子:

1

2

3

4

5

6

class GetAge:

    def __init__(self,name,age):

        self.name = name

        self.age = age

        print('%s的年龄为%d'%(name,age))

GetAge('小明',18)

输出结果为:

1

小明的年龄为18

我们需要注意,self是必不可少的,而且需要放在第一个,然后我们在调用这个类的时候,init方法中所包含的参数个数(不包含self),一定是等同于我们在调用的时候实际参数传递的个数。


3.类的方法

我们在使用类的时候经常要自己定义方法,这一节我们就来介绍一下如何自定义方法,关于类中定义的方法,我们可以继续以教室为例,当我们定义了一间教室,这间教室里可以学习语文、数学和英语,那么当一个学生到了这个班级里之后,也就具备了在这个教室学习语文数学和英语的能力,有课外兴趣的也可以根据自己的选择去其他学科的知识,通过这个例子我们来进行这一节的学习。

首先我们需要定义一个类:

1

2

3

4

5

6

class Study:

    def __init__(self):

        print('在这个班级必须学习语文')

        print('在这个班级必须学习数学')

        print('在这个班级必须学习英语')

lihua = Study()#使用Study这个类,然后就可以使用其中的方法

输出结果为:

1

2

3

在这个班级必须学习语文

在这个班级必须学习数学

在这个班级必须学习英语

这是我们关于类的最简使用方式:通过创建一个类,然后在类中创建了几个方法,通过调用类之后直接使用类中的方法。

如果想要添加一个学习其他学科的功能,我们需要在类中先添加一个方法:

1

2

def study_others(self,others):

    print('在这个班级可以学习%s'%others)

然后使用的时候注意参数的传递。

1

lihua.study_others('历史')

输出结果为:

1

在这个班级可以学习历史中

下面我们通过例子来进一步了解构造方法和自定义方法的结合。

我们在图书馆借阅书籍的时候一般是通过个人信息来存储我们的借还记录。

看下面的例子:

1

2

3

4

5

6

7

8

9

10

11

12

class Library:

    def __init__(self,name,id,age):

            self.name = name

            self.id = id

            self.age =age

    def borrow(self,bookname):

            self.bookname = bookname

            print('%s借阅了书籍--%s'%(self.name,self.bookname))

            print('借阅者学号为%d,年龄为%s'%(self.id,self.age))

                        print('借书成功!')

xiaoming = Library('小明',1001,20)

xiaoming.borrow('Python教程')

输出结果为:

1

2

3

小明借阅了书籍--Python教程

借阅者学号为1001,年龄为20

借书成功!

从上面的例子中我们来分析一下,我们首先在init方法中定义了3个参数,分别为姓名、学号和年龄,因此我们在使用这个类方法的时候,传递了三个实际参数,然后xiaoming就已经调用了这个类。因为init方法是初始构造方法,因此在borrow方法中可以直接使用init中的数据,当xiaoming使用借书方法的时候,调用了构造方法中的信息完成借书操作。

我们再通过一个例子来加深一下对该方法的理解。

书店里有一百本Python学习教程,如果有人买了一本那么该书就少了一本,书店老板会时不时的订购这本书,一次订购十本。

代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

class BookStore:

    def __init__(self,bookname,bookcount):

        self.bookname = bookname

        self.bookcount = bookcount

    def sell(self):

        self.bookcount -= 1

        print('%s现在有%s本'%(self.bookname,self.bookcount))

    def buy(self):

        self.bookcount += 10

        print('%s现在有%s本' % (self.bookname, self.bookcount))

own = BookStore('Python学习教程',100)

own.sell()

own.sell()

own.buy()

own.sell()

输出结构为:

1

2

3

4

Python学习教程现在有99

Python学习教程现在有98

Python学习教程现在有108

Python学习教程现在有107

在上面的例子中,构造方法中定义了书的名字和书的数量,然后在下面定义了卖书和买书的方法,然后我们使用own调用了BookStore类,然后再通过类中的方法实现卖书和买书的操作。

4.类的继承

关于继承重写多态这三种类型,我们在日常使用过程中使用最多的是继承,当我们需要很多类似的子类的时候,如果我们一一定义会浪费我们很多的空间和时间,在这个时候我们只要定义一个父类,也就是定义一个模板,然后全部继承父类的属性和行为即可,工厂在批量生产某个机械配件的时候,并不是每生产一个都需要画一个图纸,而是根据一个图纸进行批量生产,我们在程序里使用继承的时候也是采用的这种思想,但是当我们想要对某个继承来的配件进行一定更改的时候,我们可以采用重写的方法,而多态则是综合了继承和重写,下面我们依次进行学习。

所谓继承,就是子继承父。

根据例题我们来学习一下继承。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

class Base:#定义一个名为Base的父类

    def __init__(self,name,age,id):

        self.name = name

        self.age = age

        self.id = id

        print('继承了Base这个类')

        print('我的名字:',self.name)

        print('我的年龄:',self.age)

        print('我的学号:',self.id)

    def goto_school(self):

        print(self.name,'正在使用Base类中的goto_school方法去上学')

class Student(Base):#继承父类的时候会继承父类中的所有方法

    pass

xiaoming = Student('小明',20,1001)

xiaoming.goto_school()

输出结果为:

1

2

3

4

5

继承了Base这个类

我的名字: 小明

我的年龄: 20

我的学号: 1001

小明 正在使用Base类中的goto_school方法去上学

5.类的重写

重写是基于继承的一种方法,也就是说如果我们不想要从父类中继承来的属性或者行为,我们可以在子类中进行方法的重写。

看下面的例子:

1

2

3

4

5

6

7

8

9

10

11

class Base:#定义一个父类

    def __init__(self,name):

        self.name = name

        print('继承了Base')

    def eat_dinner(self):

        print(self.name,'晚饭吃火锅')

class Student(Base):#继承父类的时候会继承父类中的所有方法

    def eat_dinner(self):

        print(self.name,'晚饭吃自助餐')

xiaoming = Student('小明')

xiaoming.eat_dinner()

输出结果为:

1

2

继承了Base

小明 晚饭吃自助餐

通过这个例子我们可以看出,虽然Student方法继承了Base中的方法并输出了‘继承了Base’,但是当xiaoming使用eat_dinner方法的时候,他使用的是子类重写过后的方法,而不是继承而来的方法。我们在重写的时候需要注意,重写的方法要保持名字和参数的一致性

6.类的多态

关于多态,多态就是上面两种方式的结合,通过多态我们可以写出各种各样的程序。

看下图:

多态

多态即一个方法在父类子类中存在着不同种用法,可以分别调用。

看下面的例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

class Base:

    def __init__(self,name):

        self.name =name

        print('%s会读书'%self.name)

    def reading(self):

        print('%s在读语文书'%self.name)

class Inherit_One(Base):

    def reading(self):

        print('%s在读英语书'%self.name)

class Inherit_Two(Base):

    def reading(self):

        print('%s在看漫画书'%self.name)

a = Base('a')

a.reading()

b = Inherit_One('b')

b.reading()

c = Inherit_Two('c')

c.reading()

输出结果为:

1

2

3

4

5

6

a会读书

a在读语文书

b会读书

b在读英语书

c会读书

c在看漫画书

可以看出每个继承者都重写了reading方法,然后我们在调用这个方法的时候通过不同的类去调用,这种方式可以帮助我们在不同类中定义相同名字的不同方法,看似混乱,但是在我们现实中的各种管理系统当中往往都是离不开多态的使用。

 


http://www.mrgr.cn/news/57761.html

相关文章:

  • LabVIEW提高开发效率技巧----离线调试
  • Axure垂直菜单展开与折叠
  • 我的世界之合成
  • 机器学习2
  • 软件分享丨豆包电脑端 AI 助手
  • 搭建微信AI机器人
  • ubuntu系统如何在本地查看服务器上的tensorboard结果
  • Python3入门--数据类型
  • 经典功率谱估计的原理及MATLAB仿真(自相关函数BT法、周期图法、bartlett法、welch法)
  • 机器学习在智能水泥基复合材料中的应用与实践
  • 在 Go 中,如何实现一个带过期时间的字典映射
  • 富格林:可信操作助力有效追损
  • C/C++每日一练:实现冒泡排序
  • uniapp实现多文件下载,保存到本地
  • 凯撒密码-图形化实现(Scratch)
  • LeetCode常用算法模板
  • 国内 Docker 镜像加速与 GitHub 加速服务:CNPROXY.TOP
  • 【资深码农】环境搭建篇
  • 【算法】Bellman-Ford单源最短路径算法(附动图)
  • Orthanc局域网访问、IP访问、远程访问服务器
  • Linux的目录结构 常用基础命令(2)
  • 【网络】:网络基础
  • 解决url含%导致404错误
  • flink使用hikariCP数据库连接池,导致连接泄露
  • 【含文档】基于ssm+jsp的爱旅行平台的设计与实现(含源码+数据库+lw)
  • uboot源码makefile基础及启动流程梳理