【Python基础】Python 面向对象编程(上篇)
我的施工计划图
已完成专题包括:
1我的施工计划
2数字专题
3字符串专题
4列表专题
5流程控制专题
6编程风格专题
7函数使用专题
今天是面向对象编程的上篇:基础专题
Python 面向对象编程
面向对象程序设计思想,首先思考的不是程序执行流程,它的核心是抽象出一个对象,然后构思此对象包括的数据,以及操作数据的行为方法。
本专题主要讨论面向对象编程(OOP)的基础和进阶知识,实际开发模型中OOP的主要实践,尽量使用最贴切的例子。
基础专题
1 类定义
动物是自然界一个庞大的群体,以建模动物类为主要案例论述OOP编程。
Python语言创建动物类的基本语法如下,使用class
关键字定义一个动物类:
class Animal():pass
类里面可包括数据,如下所示的Animal
类包括两个数据:self.name
和self.speed
:
class Animal():def __init__(self,name,speed):self.name = name # 动物名字self.speed = speed # 动物行走或飞行速度
注意到类里面通过系统函数__init__
为类的2个数据赋值,数据前使用self
保留字。
self
的作用是指名这两个数据是实例上的,而非类上的。
同时注意到__init__
方法的第一个参数也带有self
,所以也表明此方法是实例上的方法。
2 实例
理解什么是实例上的数据或方法,什么是类上的数据,需要先建立实例
的概念,类
的概念,如下:
# 生成一个名字叫加菲猫、行走速度8km/h的cat对象
cat = Animal('加菲猫',8)
cat
就是Animal
的实例,也可以一次创建成千上百个实例,如下创建1000只蜜蜂:
bees = [Animal('bee'+str(i),5) for i in range(1000)]
总结:自始至终只使用一个类Animal
,但却可以创建出许多个它的实例,因此是一对多的关系。
实例创建完成后,下一步打印它看看:
In [1]: print(cat)
<__main__.Animal object at 0x7fce3a596ad0>
结果显示它是Animal
对象,其实打印结果显示实例属性信息会更友好,那么怎么实现呢?
3 打印实例
只需重新定义一个系统(又称为魔法)函数__str__
,就能让打印实例显示的更加友好:
class Animal():def __init__(self,name,speed):self.name = name # 动物名字self.speed = speed # 动物行走或飞行速度def __str__(self):return '''Animal({0.name},{0.speed}) is printedname={0.name}speed={0.speed}'''.format(self)
使用0.数据名称
的格式,这是类专有的打印格式。
现在再打印:
cat = Animal('加菲猫',8)
print(cat)
打印信息如下:
Animal(加菲猫,8) is printedname=加菲猫speed=8
以上就是想要的打印格式,看到实例的数据值都正确。
4 属性
至此,我们都称类里的name
和speed
称为数据,其实它们有一个专业名称:属性。
同时,上面还有一个问题我们没有回答完全,什么是类上的属性?
如下,在最新Animal
类定义基础上,再添加一个cprop
属性,它前面没有self
保留字:
class Animal():cprop = "我是类上的属性cprop"def __init__(self,name,speed):self.name = name # 动物名字self.speed = speed # 动物行走或飞行速度def __str__(self):return '''Animal({0.name},{0.speed}) is printedname={0.name}speed={0.speed}'''.format(self)
类上的属性直接使用类便可引用:
In [1]: Animal.cprop
Out[1]: '我是类上的属性cprop'
类上的属性,实例同样可以引用,并且所有的实例都共用此属性值:
In [1]: cat = Animal('加菲猫',8)
In [2]: cat.cprop
Out[2]: '我是类上的属性cprop'
Python作为一门动态语言,支持属性的动态添加和删除。
如下cat
实例原来不存在color
属性,但是赋值时不光不会报错,相反会直接将属性添加到cat
上:
cat.color = 'grap'
那么,如何验证cat
是否有color
属性呢?使用内置函数hasattr
:
In [24]: hasattr(cat,'color') # cat 已经有`color`属性
Out[24]: True
但是注意:以上添加属性方法仅仅为cat
实例本身添加,而不会为其他实例添加:
In [26]: monkey = Animal('大猩猩',2)
In [27]: hasattr(monkey,'color')
Out[27]: False
monkey
实例并没有color
属性,注意与__init__
创建属性方法的区别。
5 private,protected,public
像name
和speed
属性,引用此实例的对象都能访问到它们,如下:
# 模块名称:manager.pyimport timeclass Manager():def __init__(self,animal):self.animal = animaldef recordTime(self):self.__t = time.time()print('feeding time for %s(行走速度为:%s) is %.0f'%(self.animal.name,self.animal.speed,self.__t))def getFeedingTime(self):return '%0.f'%(self.__t,)
使用以上Manager
类,创建一个cat
实例,xiaoming
实例引用cat
:
cat = Animal('加菲猫',8)
xiaoming = Manager(cat)
xiaoming
的recordTime
方法引用里,引用了animal的两个属性name
和speed
:
In[1]: xiaoming.recordTime()Out[1]: feeding time for 加菲猫(行走速度为:8) is 1595681304
注意看到self.__t
属性,它就是一个私有属性,只能被Manager
类内的所有方法引用,如被方法getFeedingTime
方法引用。但是,不能被其他类引用。
如果我们连speed
这个属性也不想被其他类访问,那么只需将self.speed
修改为self.__speed
:
同时Manager
类的self.animal.speed
修改为self.animal.__speed
,再次调用下面方法时:
xiaoming.recordTime()
就会报没有__speed
属性的异常,从而验证了__speed
属性已经变为类内私有,不会暴露在外面。
总结:name
属性相当于java的public属性,而__speed
相当于java的private属性。
下面在说继承时,讲解protected
属性,实际上它就是带有1个_
的属性,它只能被继承的类所引用。
6 继承
上面已经讲完了OOP三大特性中的封装性,而继承是它的第二大特性。子类继承父类的所有public
和protected
数据和方法,极大提高了代码的重用性。
如上创建的Animal
类最新版本为:
class Animal():cprop = "我是类上的属性cprop"def __init__(self,name,speed):self.name = name # 动物名字self.__speed = speed # 动物行走或飞行速度def __str__(self):return '''Animal({0.name},{0.__speed}) is printedname={0.name}speed={0.__speed}'''.format(self)
现在有个新的需求,要重新定义一个Cat
猫类,它也有name
和speed
两个属性,同时还有color
和genre
两个属性,打印时只需要打印name
和speed
两个属性就行。
因此,基本可以复用基类Animal
,但需要修改__speed
属性为受保护(protected
)的_speed
属性,这样子类都可以使用此属性,而外部还是访问不到它。
综合以上,Cat
类的定义如下:
class Cat(Animal):def __init__(self,name,speed,color,genre):super().__init__(name,speed)self.color = color self.genre = genre
首先使用super()
方法找到Cat
的基类Animal
,然后引用基类的__init__
方法,这样复用基类的方法。
使用Cat
类,打印时,又复用了基类的 __str__
方法:
jiafeimao = Cat('加菲猫',8,'gray','CatGenre')
print(jiafeimao)
打印结果:
Animal(加菲猫,8) is printedname=加菲猫speed=8
以上就是基本的继承使用案例,继承要求基类定义的数据和行为尽量标准、尽量精简,以此提高代码复用性。
7 多态
如果说OOP的封装和继承使用起来更加直观易用,那么作为第三大特性的多态,在实践中真正运用起来就不那么容易。有的读者OOP编程初期,可能对多态的价值体会不深刻,甚至都已经淡忘它的存在。
那么问题就在:多态到底真的有用吗?到底使用在哪些场景?
多态价值很大,使用场景很多,几乎所有的系统或软件,都能看到它的应用。这篇文章尽可能通过一个精简的例子说明它的价值和使用方法。如果不用多态,方法怎么写;使用多态,又是怎么写。
为了一脉相承,做到一致性,仍然基于上面的案例,已经创建好的Cat
类要有一个方法打印和返回它的爬行速度。同时需要再创建一个类Bird
,要有一个方法打印和返回它的飞行速度;
如果不使用多态,为Cat
类新增一个方法:
class Cat(Animal):def __init__(self,name,speed,color,genre):super().__init__(name,speed)self.color = color self.genre = genre# 添加方法def getRunningSpeed(self):print('running speed of %s is %s' %(self.name, self._speed))return self._speed
重新创建一个Bird
类:
class Bird(Animal):def __init__(self,name,speed,color,genre):super().__init__(name,speed)self.color = color self.genre = genre# 添加方法def getFlyingSpeed(self):print('flying speed of %s is %s' %(self.name, self._speed))return self._speed
最后,上面创建的Manager
类会引用Cat
和Bird
类,但是需要修改recordTime
方法,因为Cat它是爬行的,Bird它是飞行的,所以要根据对象类型的不同做逻辑区分,如下所示:
# 模块名称:manager.pyimport time
from animal import (Animal,Cat,Bird)class Manager():def __init__(self,animal):self.animal = animaldef recordTime(self):self.__t = time.time()if isinstance(self.animal, Cat):print('feeding time for %s is %.0f'%(self.animal.name,self.__t))self.animal.getRunningSpeed()if isinstance(self.animal,Bird):print('feeding time for %s is %.0f'%(self.animal.name,self.__t))self.animal.getFlyingSpeed()def getFeedingTime(self):return '%0.f'%(self.__t,)
如果再来一个类,我们又得需要修改recordTime
,再增加一个if
分支,从软件设计角度讲,这种不断破坏封装的行为不可取。
但是,使用多态,就可以保证recordTime
不被修改,不必写很多if分支。怎么来实现呢?
首先,在基类Animal
中创建一个基类方法,然后Cat
和Bird
分别重写此方法,最后传入到Manager
类的animal
参数是什么类型,在recordTime
方法中就会对应调用这个animal
实例的方法,这就是多态。
代码如下:
animal2.py 模块如下:
# animal2.py 模块class Animal():cprop = "我是类上的属性cprop"def __init__(self,name,speed):self.name = name # 动物名字self._speed = speed # 动物行走或飞行速度def __str__(self):return '''Animal({0.name},{0._speed}) is printedname={0.name}speed={0._speed}'''.format(self)def getSpeedBehavior(self):pass class Cat(Animal):def __init__(self,name,speed,color,genre):super().__init__(name,speed)self.color = color self.genre = genre# 重写方法def getSpeedBehavior(self):print('running speed of %s is %s' %(self.name, self._speed))return self._speedclass Bird(Animal):def __init__(self,name,speed,color,genre):super().__init__(name,speed)self.color = color self.genre = genre# 重写方法def getSpeedBehavior(self):print('flying speed of %s is %s' %(self.name, self._speed))return self._speed
manager2.py 模块如下:
# manager2.py 模块import time
from animal2 import (Animal,Cat,Bird)class Manager():def __init__(self,animal):self.animal = animaldef recordTime(self):self.__t = time.time()print('feeding time for %s is %.0f'%(self.animal.name,self.__t))self.animal.getSpeedBehavior()def getFeedingTime(self):return '%0.f'%(self.__t,)
recordTime
方法非常清爽,不需要任何if逻辑,只需要调用我们定义的Animal
类的基方法getSpeedBehavior
即可。
在使用上面所有类时,Manager(jiafeimao)
传入Cat
类实例时,recordTime
方法调用就被自动指向Cat
实例的getSpeedBehavior
方法;
Manager(haiying)
传入Bird
类实例时,自动指向Bird
实例的getSpeedBehavior
方法,这就是多态和它的价值,Manager类的方法不必每次都修改,保证了类的封装性。
if __name__ == "__main__":jiafeimao = Cat('jiafeimao',2,'gray','CatGenre')haiying = Bird('haiying',40,'blue','BirdGenre')Manager(jiafeimao).recordTime()print('#'*30)Manager(haiying).recordTime()
总结
以上就是面向对象编程专题的基础部分,大纲如下:
Python 面向对象编程
基础专题
1 类定义
2 实例
3 打印实例
4 属性
5 private,protected,public
6 继承
7 多态
总结
往期精彩回顾适合初学者入门人工智能的路线及资料下载机器学习及深度学习笔记等资料打印机器学习在线手册深度学习笔记专辑《统计学习方法》的代码复现专辑
AI基础下载机器学习的数学基础专辑获取一折本站知识星球优惠券,复制链接直接打开:https://t.zsxq.com/662nyZF本站qq群1003271085。加入微信群请扫码进群(如果是博士或者准备读博士请说明):
【Python基础】Python 面向对象编程(上篇)相关推荐
- python基础之面向对象编程
python基础之面向对象编程 面向对象编程思想 面向对象是一门编程思想,编程思想仅仅是一门思想,与任何技术无关 核心是对象两字,对象可以理解为特征与技能的结合体 基于该编程思想编写程序,就好比创造世 ...
- 带你学python基础:面向对象编程
面向对象编程是个啥呢,其实,在传统的语言中,比如 C 语言,是不存在面向对象编程这个概念的,那时候的语言只有面向过程编程,也就是我们写代码从头写到底,最多也就是有函数.所以,这样的代码风格是比较难维护 ...
- Python基础课程-面向对象编程
Python面向对象编程 在本文中,您将学习Python中的OOP的以下基本概念: Python类 对象实例 定义和使用方法 OOP继承 什么是面向对象编程(OOP)? 面向对象编程(Object-o ...
- Day7 - Python基础7 面向对象编程进阶 --转自金角大王
本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 经典 ...
- python面向对象编程的优点-Python 基础知识----面向对象编程
一.面向对象编程介绍 面向过程编程: 核心是过程二字,过程指的是解决问题的步骤,即先做什么再干什么然后干什么. 基于该思想编写程序好比在设计一条流水线,是一种机械式的思维方式. 优点:复杂的问题流程化 ...
- Python基础学习——面向对象编程(第一讲:面向对象概述、面向对象三个基本特征(封装性、继承性、多态性)、类和对象(定义类、创建和使用对象、实例变量、类变量、构造方法、实例方法、类方法、静态方法))
面向对象是Python最重要的特性,在Python中一切数据类型都是面向对象的. 1.面向对象概述 面向对象的编程思想是,按照真实世界客观事物的自然规律进行分析,客观世界中存在什么样的实体,构建软件系 ...
- Day6 - Python基础6 面向对象编程 --转自金角大王
本节内容: 面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法. 引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏,你 ...
- Python基础——6面向对象编程
类和实例 类是抽象的模版,例如汽车:而实例则是拥有相同方法的类的实现,例如汽车里面有大众.宝马.奔驰等等,这些车都能在地面上跑,但是它们的具体数据可以不一样. calss Student(object ...
- Python基础:面向对象编程实战——简易图书管理系统
简易图书管理系统主要有以下功能:1.查询所有书籍2.添加书籍3.借阅书籍4.归还书籍5.退出系统.代码实现主要为: class Book:def __init__(self, name, author ...
- 第二章(1):Python入门:语法基础、面向对象编程和常用库介绍
第二章(1):Python入门:语法基础.面向对象编程和常用库介绍 目录 第二章(1):Python入门:语法基础.面向对象编程和常用库介绍 1. Python 简介 1.1 Python 是什么? ...
最新文章
- 15 Small-Space Tricks We're Stealing from Real Tiny Apartments
- 单链表 操作的18种算法
- mvc html绑定变量,c# – Asp.Net MVC 3使用变量对象进行自定义模型绑定
- java APIs for xml --------dom(2)
- SLS机器学习介绍(05):时间序列预测
- apache cxf之 一个简单的JAX-WS服务程序
- python程序设计pdf机械出版_Python程序设计
- APMCon2017 | 一大波技术大神来袭,你要的性能优化干货这里全都有
- ​手机APP应用软件开发
- esxi6.7 vSAN 运行状况 控制器固件版本 控制器实用程序问题
- 要留住优秀员工,除了钱,你还可以用什么?
- 计算器linux源码,强悍的C++程序实现计算器的linux源程序(国外英文资料).doc
- eclipsemaven服务器显示404,eclipse-HTTP状态404-请求的资源(/)不可用
- 江南农村商业银行容器云平台建设经验分享
- ajax读取json文件 / 跨域问题
- Nginx安装配置报错详解
- JS 通过日期判断当前日期所在周的周一到周日的日期
- 七步爬取淘宝天猫bra销售数据,分析中国女性胸部大小分布比例
- 职称计算机考科目代码表,职称计算机考试科目
- 数据仓库、大数据平台、数据中台的区别
热门文章
- lucene3.5学习笔记02--创建索引和建立搜索
- 配置MySQL5.7基于GTID的复制
- [leetcode]83.Remove Duplicates from Sorted List
- INT(M)表示什么意思?
- Codeforces Round #301 (Div. 2) B. School Marks
- mac下profile文件(转载)
- 社区医学的研究方法:调查、流行病学研究、方案评估、临床试验Research Methods in Community Medicine: Surveys, Epidemiological Resear
- qPCR实验疑难杂问解答
- Android studio | From Zero To One ——初级控件(屏幕显示)
- Matlab | 数字信号处理:FIR滤波器结构的实现