第7章 面向对象程序设计

7.1 面向对象概述

面向对象(Object Oriented)的英文缩写是OO,它是一种设计思想。从20世纪60年代提出面向对象的概念到现在,它已经发展成为一种比较成熟的编辑思想,并且逐步成为目前软件开发领域的主流计技术。如我们经常听说的面向对象编程(Object Oriented Programming,即OOP)就是主要针对大型软件设计而提出的,它可以使软件设计更加灵活,并且能更好地进行代码复用。

面向对象中的对象(Object),通常是指客观世界中存在的对象,具有唯一性,对象之间各不相同,各有各的特点,么一个对象都有自己的运动规律和内部状态;对象与对象之间有时可以相互联系、相互作用。另外,对象也可以是一个抽象的事物,例如,可以从圆形、正方形、三角形等图形抽象出一个简单图形,简单图就是一个对象,它有自己的属性和行为,图形中边的个数是它的属性,图形的面积也是它的属性,输出图形的面积就是它的行为。概括地讲,面向对象技术是一种从组织结构上模拟客观世界的方法。

7.1.1 对象

对象,是一个抽象概念,英文称作“Object”,表示任意存在的事物。世间万物皆对象!现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体,如一个人。

通常将对象划分为两个部分,即静态部分和动态部分。静态部分被称为“属性”,任何对象都具备自身属性,这些属性不仅是客观存在的,而且是不能被忽视的,如人的性别。动态部分指的是对象的行为,即对象执行的动作,如人可以跑步。

说明:在Python中,一切都是对象。即不仅是具体的事物称为对象,字符串、函数等也都是对象。这说明Python天生就是面向对象的。

7.1.2 类

类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类。例如,把雁群比作大雁类,那么大雁类就具备了喙、翅膀和爪等属性,觅食、飞行和睡觉等行为,而一只要从北方飞往南方的大雁被视为大雁类的一个对象。大雁类和大雁对象的关系。

在Python语言中,类是一种抽象概念,如定义一个大雁类(Geese),在该类中,可以定义每个对象共有的属性和方法;而一只要从北方飞往南方的大雁则是大雁类的一个对象(wildGeese),对象是类的实例。有关类的具体实现将在7.2节进行详细介绍。

7.1.3 面向对象程序设计的特点

面向对象程序设计具有三大基本特征:封装、继承和多态。

1. 封装

封装是面向对象编程的核心思想,将对象的属性和行为封装起来,其载体就是类,类通常会对客户隐藏其现实细节,这就是封装的思想。例如,用户使用计算机,只需要使用手机敲击键盘就可以实现一些功能,而不需要知道计算机内部是如何工作的。

采用封装思想保证了类内部数据结构的完整行,使用该类的用户不能这看到类中的数据结构,而只能执行类允许公开的数据,这样就避免了外部对内部数据的影响,提高了程序的可维护性。

2. 继承

矩形、菱形、平行四边形和梯形等都是四边形。因为四边形与它们具有共同的特征:拥有4条边。只要将四边矩形适当延伸,就会得到矩形、菱形、平行四边形和梯形4 种图形。以平行四边形为例,如果把平行四边形的延伸,那么平行四边形就复用了四边形的属性和行为,同时添加了平行四边形特有的属性和行为,如平行四边形的对边平行且相等。在Python中,可以把平行四边形类看作是继承四边形类后产生的类,其中,将类似于平行四边形的类称为子类,将类似于四边形的类称为父类和超类。值得注意的是,在阐述平行四边形和四边形的关系时,可以说平行四边形是特殊的四边形,但不能说四边形是平行四边形。同理,Python 中可以说子类的实例都是父类的实例,但不能说父类的实例是子类的实例。

综上所述,继承是实现重复利用的重要手段,子类通过继承复用了父类的属性和行为的同时又添加了子类特有的属性和行为。

3. 多态

将父类对象应用于子类的特征就是多态。比如创建一个螺丝类,螺丝类有两个属性:粗细和螺纹密度;然后在创建了两个类,一个是长螺丝类,一个短螺丝类,并且它们都继承了螺丝类。这样长螺丝类和短螺丝类不仅具有相同的特征(粗细形同,且螺纹密度也相同),还具有不同的特征(一个长,一个短,长的可以用来固定大型支架,短的可以固定生活中的家具)。综上所述,一个螺丝类衍生出不同的子类,子类继承父类特征的同时,也具备了自己的特征,并且能够实现不同的效果,这就是多态化的结构。

7.2 类的定义和使用

在Python 中,类表示具有相同属性和方法的对象的集合。在使用类时,需要先定义类,然后再创建类的实例,通过类的实例就可以访问类中的属性和方法了。

7.2.1 定义类

在Python 中,类的定义使用class 关键字来实现,语法如下:

class ClassName:
'''类的帮助信息''' # 类文档字符串
statement # 类体

参数说明:

  • ClassName:用于指定类名,一般使用大写字母开头,如果类名中包括两个单词,第二个单词的首字母也大写,这种命名方法也称为“驼峰式命名法”,这是惯例。当然也可以根据自己的习惯命名,但是一般推荐按照惯例来命名。
  • '''类的帮助信息''':用于指定类的文档字符串,定义该字符串后,在创建类的对象是,输入类名和左侧的括号“(” 后,将显示该信息。
  • statement:类体,主要由类变量(或类成员)、方法和属性等定义语句组成。如果在定义类时,没想好类的具体功能,可可以在类体中直接使用pass 语句代替。

例如,下面以大雁为例声明一个类,代码如下:

class Geese:
'''大雁类'''
pass

7.2.2 创建类的实例

定义完类后,并不会真正的创建一个实例。这有点像一个汽车的设计图。设计图可以告诉你汽车看上去怎样,但设计图本身不是一个汽车。你不能开走它,它只能用来创造真正的汽车,而且可以使用它制造很多汽车。那么如何创建实例呢?

class语句本身不创建该类的任何实例。所以在类定义完成以后,可以创建类的实例,即实例化该类的对象。创建类的实例的语法如下:

ClassName(parameterlist)

其中,ClassName 是必选参数,用于指定具体的类;parameterlist 是可选参数,当创建一个类时,没有创建__init__()方法(该方法将在7.2.3 小节进行详细介绍),或者__init__() 方法只有一个self 参数时,parameterlist 可以省略。

class Geese:
'''大雁类'''
pass
wildGoose = Geese() # 创建大雁类的实例
print(wildGoose)

执行上面的代码后,将显示类似下面的内容:

<__main__.Geese object at 0x028BD430>

从上面的执行结果中可以看出,wildGoose是Geese类的实例。

7.2.3 创建__init__() 方法

在创建类后,可以手动创建一个__init__() 方法。该方法是一个特殊的方法,类似Java 语言中的构造方法。每当创建一个类的新实例时,Python 都会自动执行它。__init__() 方法必须包含一个self 参数,并且必须是一个第一个参数。self 参数是一个指向实例本身的引用,用于访问类中的属性和方法。在方法调用时会自动传递实际参数self,因此当__init__() 方法只有一个参数时,在创建类的实例时,就不需要指定实际参数了。

说明:在__init__() 方法的名称中,开头和结尾处是两个下划线(中间没有空格),这是一种约定,旨在区分Python 默认方法和普通方法。

例如,下面仍然以大雁为例声明一个类,并且创建__init__() 方法,代码如下:

class Geese:
'''大雁类'''
def __init__(self): #构造方法
print('我是大雁类!')
wildGoose = Geese() # 创建大雁类的实例

运行上面的代码,将输出以下内容:

我是大雁类!

从上面的运行结果可以看出,在创建大雁类的实例时,虽然没有为__init__() 方法指定参数,但是该方法会自动执行。

在__init__() 方法中,除了self 参数外,还可以自定义一些参数,参数间使用逗号“,” 进行分隔。

例如,下面的代码将在创建__init__()方法时,在指定3个参数,分别是beak、wing和claw。

lass Geese:
'''大雁类'''
def __init__(self,beak,wing,claw): #构造方法
print('我是大雁类!我有以下特征:')
print(beak) # 输出喙的特征
print(wing) # 输出翅膀的特征
print(claw) # 输出爪子的特征
beak_1 = "喙的基本较高,长度和头部的长度几乎相等" # 喙的特征
wing_1 = "翅膀长而尖" # 翅膀的特征
claw_1 = "爪子是蹼状的" # 爪子的特征
wildGoose = Geese(beak_1,wing_1,claw_1) # 创建大雁类的实例

执行上面的代码,结果如下。

我是大雁类!我有以下特征:
喙的基本较高,长度和头部的长度几乎相等
翅膀长而尖
爪子是蹼状的

7.2.4 创建类的成员并访问

类的成员主要有实例方法和数据成员组成。在类中创建了类的成员后,可以通过类的实例进行访问。

1. 创建实例方法并访问

所谓实例方法是指在类中定义的函数。该函数是一种在类的实例上操作的函数。同__init__() 方法一样,实例方法的第一个参数必须是self,并且必须包含一个self 参数。创建实例方法的语法格式如下:

def functionName(self,parameterlist):
block

参数说明:

  • functionName:用于指定方法名,一般使用小写字母开头。
  • self:必要参数,表示类的实例,其名称可以是self 以外的单词,使用self 只是一个惯例而已。
  • parameterlist:用于指定出self 参数以外的参数,各参数间使用逗号“,” 进行分隔。
  • block:方法体,显示的具体功能。

说明:实例方法和Python 中的函数的主要区别就是,函数实现的是某个独立的功能,而实例方法是显示类中的一个行为,是类的一部分。

实例方法创建完成后,可以通过类的实例名称和点(.)操作符进行访问,语法格式如下:

intanceName.functionName(parametervalue)

参数说明:

  • instanceName:为类的实例名称。
  • functionName:为要调用的方法名称。
  • parametervalue:表示为方法指定对应的实际参数,其值的个数与创建实例方法中parameterlist的个数相同。

实例01:创建大雁并定义飞行方法

class Geese:
'''大雁类'''
def __init__(self,beak,wing,claw): #构造方法
print('我是大雁类!我有以下特征:')
print(beak) # 输出喙的特征
print(wing) # 输出翅膀的特征
print(claw) # 输出爪子的特征
def fly(self,state): # 定义飞行方法
print(state)
'''****************调用方法***************'''
beak_1 = "喙的基本较高,长度和头部的长度几乎相等" # 喙的特征
wing_1 = "翅膀长而尖" # 翅膀的特征
claw_1 = "爪子是蹼状的" # 爪子的特征
wildGoose = Geese(beak_1,wing_1,claw_1) # 创建大雁类的实例
wildGoose.fly("我飞行的时候,一会儿排成个人字,一会儿排成个一字") # 调用实例方法

运行结果

我是大雁类!我有以下特征:
喙的基本较高,长度和头部的长度几乎相等
翅膀长而尖
爪子是蹼状的
我飞行的时候,一会儿排成个人字,一会儿排成个一字

多学两招:在创建实例方法时,也可以和创建函数是一样为参数设置默认值。但是被设置了默认值的参数必须位于所有参数的最后(即最右侧)。例如,可以将实例01的第8行代码修改为以下内容:

def fly(self,state = '我会飞行'):

2. 创建数据成员并访问

数据成员是指在类中定义的变量,即属性,根据定义位置,又可以分为类属性和实例属性。

  • 类属性

类属性是指定义在类中,并且在函数体外的属性。类属性可以在类的所有实例之间共享值,也就是在所有实例化的对象中共用。

说明:类属性可以通过类名称或者实例名访问。

……

  • 实例属性

实例出行是指定义在类的方法中的属性,只作用于当前实例中。

7.2.5 访问限制

在类的内部可以定义属性和方法,而在类的外部则可以直接调用属性或方法来操作数据,从而隐藏了类内部的复杂逻辑。但是Python 并没有对属性和方法名前面添加单下划线(_foo)、双下划线(__foo)或首尾加双下划线(__foo__),从而限制访问权限。其中,单下划线、双下划线、首尾双下划线的作用如下:

(1)首尾双下划线表示定义特殊方法,一般是系统定义名字,如__init__()。

(2)以单下划线开头的表示protected(保护)类型的成员,只允许本身和子类进行访问,但不能使用“from module imort*”语句导入。

……

(3)双下划线表示private(私有)类型成员,只允许定义该方法的类本身进行访问,而且也不能通过类的实例进行访问,但是可以通过“类的实例名._类名__xxx”方式访问。

7.3 属性(property)

本节介绍的属性与7.2.4小节介绍的类属性和实例属性不同。7.2.4小节介绍的属性将返回存储的值,而本节介绍的属性则是一种特殊的属性,访问它时将计算它的值。另外,该属性还可以为属性添加安全保护机制。

7.3.1 创建用于计算的属性

在Python中,可以通过@property(装饰器)将一个方法转换为属性,从而实现用于计算的属性。将方法转换为属性后,可以直接通过方法名来访问方法,而不需要再添加一对小括号“o”,这样可以让代码更加简洁。

通过@property创建用于计算的属性的语法格式如下:

@property
def methodname(self):
block

参数说明:

  • methodname:用于指定方法名,一般使用小写字母开头。该名称最后将作为创建的属性名。
  • self:必要参数,表示类的实例。
  • block:方法体,实现的具体功能。在方法体中,通常以return语句结束,用于返回计算结果。

……

注意:通过@property转换后的属性不能重复赋值,如果对其重新赋值,将抛出异常信息。

7.3.2 为属性添加安全保护机制

在Python中,默认情况下,创建的类属性或者实例是可以在类 体外进行修改的,如果想要限制其不能在类体外修改,可以将其设置为私有的,但设置为私有后,在类体外也不能获取它的值。如果想要创建一个可以读取但不能修改的属性,那么可以使用@property实现只读属性。

……

通过属性不仅可以将属性设置为只读属性,而且可以为属性设置拦截器,即允许对属性进行修改,但修改时需要遵守一定的约束。

7.4 继承

在编写类时,并不是每次都要从空白开始。当要编写的类和另一个已经存在的类之间存在一定的继承关系时,就可以通过继承来达到代码重用的目的,提高开发效率。下面介绍如果在Python中实现继承。

7.4.1 继承的基本语法

继承是面向对象编程最重要的特性之一,它源于人们认识客观世界的过程,是自然界普遍存在的一种现象。例如,我们每一个人都从祖辈和父母那里继承了一些体貌特征,但是每个人却又不同与父母,因为每个人都存在自己的一些特性,这些特性是独有的,在父母身上并没有体现。在程序设计中实现继承,表示这个类拥有它继承的类的素有公有成员或者受保护成员。在面向对象编程中,被继承的类称为父类或基类,新的类称为子类或派生类。

通过继承不仅可以实现代码的重用,还可以通过继承来顺类与类之间的关系。在Python中,可以在类定义语句中,类名右侧使用一对小括号将要继承的类名称括起来,从而实现类的继承。

……

参数说明:

  • ClassName:用于指定类名。
  • baseclasslist:用于指定要继承的基类,可以有多个,类名之间用逗号“,”分隔。如果不指定,将使所有Python对象的根类object。
  • '''类的帮助信息''':用于指定类的文档字符串,定义该字符串后,在创建类的对象时,输入类名和左侧的括号“(”后,将显示信息。
  • statement:类体,主要由类变量(或类成员)、方法和属性等定义语句组成。如果在定义类时,没想好类的具体功能,也可以在类体中直接使用pass语句代替。

……

7.4.2 方法重写

基类的成员都会被派生类继承,当基类中的某个方法不完全使用与派生类时,就需要在派生类中重写父类的这个方法,这个和Java语言中的方法重写是一样的。

7.4.3 派生类中调用基类的__init__()方法

在派生类中定义__init__()方法时,不会自动调用基类的__init__()方法。例如,定义一个Fruit类,在__init__()方法中创建类属性color,然后在Fruit类中定义一个harvest()方法。

零基础学Python--------第7章 面向对象程序设计的更多相关文章

  1. [零基础学python]为什么要开设本栏目

    这个栏目的名称叫做"零基础学Python". 如今网上已经有不少学习python的课程.当中也不乏精品.按理说,不缺少我这个基础类型的课程了.可是,我注意到一个问题.无论是课程还是 ...

  2. 零基础学python》(第二版)

    ---恢复内容开始--- 零基础学python>(第二版) python学习手册 可以离线下载,  .chn格式, 插入小幽默笑话,在学习累的时候看看笑话 放松一下 欢迎下载转载,请注明出处,谢 ...

  3. 零基础学python,python视频教程

    零基础学python,python视频教程 这是我收集到的互联网上的视频资源,所有内容均来自互联网.仅供学习使用. 目前我在也在学习过程中,会把学习过程中遇到问题以及解决问题的方式,总结到我的公众号[ ...

  4. 小甲鱼零基础学python第25讲课后习题动手练习--通讯录

    小甲鱼零基础学python第25讲课后习题动手练习---通讯录 **************************通讯录要求******************************* 输入指令: ...

  5. 零基础学Java第五节(面向对象一)

    本篇文章是<零基础学Java>专栏的第五篇文章,文章采用通俗易懂的文字.图示及代码实战,从零基础开始带大家走上高薪之路! 本文章首发于公众号[编程攻略] 类与对象 在哲学体系中,可以分为主 ...

  6. 零基础学Java第六节(面向对象二)

    本篇文章是<零基础学Java>专栏的第六篇文章,文章采用通俗易懂的文字.图示及代码实战,从零基础开始带大家走上高薪之路! 本文章首发于公众号[编程攻略] 继承 创建一个Person类 我们 ...

  7. Python学习课程零基础学Python

    python学习课程,零基础Python初学者应该怎么去学习Python语言编程?python学习路线这里了解一下吧.想python学习课程?学习路线网免费下载海量python教程,上班族也能在家自学 ...

  8. 零基础学python之构建web应用(入门级)

    构建一个web应用 前面的学习回顾: IDLE是Python内置的IDE,用来试验和执行Python代码,可以是单语句代码段,也可以是文本编辑器中的多语句程序. 四个内置数据结构:列表.字典.集合和元 ...

  9. 零基础学Python不迷茫——基本学习路线及教程!

    什么是Python? 在过去的2018年里,Python成功的证明了它自己有多火,它那“简洁”与明了的语言成功的吸引了大批程序员与大数据应用这的注意,的确,它的实用性的确是配的上它的热度.   Pyt ...

  10. 零基础学python习题 - 进入python的世界

    1. python拥有以下特性:面向对象的特性.动态性.内置的数据结构.简单性.健壮性.跨平台性.可扩展性.强类型语言.应用广泛 2. python 需要  编译 3. 以下不属于python内置数据 ...

随机推荐

  1. ArcMap AddIn之下载ArcGIS Server地图服务中的数据

    涉及到开发知识点1.ArcGIS Server地图服务 2.C# web请求获取数据 3.AddIN开发技术 工具界面: 具体涉及到的代码之后有空贴出来.先上工具 AddIn插件下载地址:点击这里下载 ...

  2. Dora.Interception,为.NET Core度身打造的AOP框架 [2]:以约定的方式定义拦截器

    上一篇<更加简练的编程体验>提供了最新版本的Dora.Interception代码的AOP编程体验,接下来我们会这AOP框架的编程模式进行详细介绍,本篇文章着重关注的是拦截器的定义.采用“ ...

  3. 安卓开发学习笔记(二):如何用Android Stuidio在res资源下创建xml视图文件

    笔者在看了相关的教程之后发现教程当中的资源已经过时了.当我们在创建了一个新的空白的工程之后,会发现其文件夹下面的分文件夹目录和官方的教程文件结构完全不同,因此会引起很多误解.笔者使用的是最新版的And ...

  4. Druid的简介

    Druid的简介 Druid首先是一个数据库连接池.Druid是目前最好的数据库连接池,在功能.性能.扩展性方面,都超过其他数据库连接池,包括DBCP.C3P0.BoneCP.Proxool.JBos ...

  5. Spring的核心接口

    ContextLoaderListener接口 Create a new ContextLoaderListenerthat will create a web application context ...

  6. 用Flutter开发的跨平台项目,完美运行在Android和IOS上,Material简洁风格,包括启动页、引导页、注册、登录、首页、体系、公众号、导航、项目,还有漂亮的妹子图库,运行极度流畅,结构清晰,代码规范,值得拥有

    Flutter学习资源汇总持续更新中...... Flutter官方网站 Flutter中文网 wendux的Flutter实战 Flutter官方exampleflutter_gallery 阿里巴 ...

  7. 面试中程序员常见的Redis"刁难"问题,值得一读!

    导读 在程序员面试过程中Redis相关的知识是常被问到的话题.作为一名在互联网技术行业打击过成百上千名的资深技术面试官,总结了面试过程中经常问到的问题.十分值得一读. Redis有哪些数据结构? 字符 ...

  8. node开发备注

    设置环境变量 // 命令行启动: "scripts": { "start": "export NODE_ENV=dev && node ...

  9. Openssh版本升级修复漏洞

    一.由于openssh版本过低当用扫描软件检测时会出现以下漏洞: 二.解决方案是升级高版本,下面是升级的步凑. 1.安装telnet工具,因为升级过程中怕失败或者重启ssh失败.我们直接yun安装即可 ...

  10. Bootstrap 字体与图标

    常用网站:icons/Font awesome/bookstrap 控制图标的大小使用 fa-lg (33%递增).fa-2x. fa-3x.fa-4x,或者 fa-5x 类 来放大图标.旋转动画 & ...