本文专栏:Python开发笔记 点击查看系列文章
1. 面向对象编程
面向对象编程
是最有效的软件编写方法之一。
在面向对象编程中,现实世界中的事物和情景,均可以使用 类
来编写表示。将要描述的对象提取公共行为,编写成类。
基于编写的类,可以创建 对象
,使得每个对象自动具备所提取的公共行为。
然后可根据实际情况,赋予每个对象自己独有的特性。
上面描述的根据类来创建对象的过程,被称为 实例化
。这让你能够使用 类的实例
。
2. 类的创建和使用
2.1 创建类
使用 类
几乎可以模拟任何东西。
比如 学生类Student
,可以用来表示任意学生。任意学生包含的信息都有 学号no
、 姓名name
、 籍贯nativePlace
等。对于每个学生的行为,都有 上课attend Class
、 下课finish Class
等。
所以可以创建 Student类
来表示。
示例(student.py):
class Student():
def __init__(self, no, name, nativePlace):
"""初始化属性no, name, nativePlace"""
self.no = no
self.name = name
self.nativePlace = nativePlace
def attend_class(self):
print(self.name + '正在上课')
def finish_class(self):
print(self.name + '已经下课')
关于这个类的定义,几点说明及注意事项如下:
- Student:这是类的名字。约定所有单词的首字母大写。
- 类中的函数称为方法。
- _init_() :初始化方法,当根据Student类来创建实例时,该方法将自动执行。约定开头和末尾各有两个下划线,避免命名冲突。
- _init_()中的self:self形参必不可少,还必须位于其他形参之前。这是因为类的创建、调用时,都自动传递实参self,这个self是一个指向实例本身的引用,使得实例能够访问类中的属性和方法。当创建实例时,self不需要传递参数,只需要给后边的值(no、name等)赋值即可。
- 属性:像上面的no、name变量,在初始化时,均使用了self 前缀,这种变量可以给类中的所有方法使用,还可以通过类的任何实例来访问,这种变量称为属性。
- 其他方法:如attend_class()和finish_class()方法,一般为当前类的具有的通用方法,其中的参数self使得该方法能够访问类中的属性。这些方法可以继续添加其他的,不在属性内的形参。
- 私有方法和属性:Python约定名称以双下划线“__”开头但不以它结尾的方法或属性,都是私有的,其他则都不是私有部分。
2.2 使用类和示例
类如何来使?先看下面这个示例。
示例:
class Student:
def __init__(self, no, name, nativePlace):
"""初始化属性no, name, nativePlace"""
self.no = no
self.name = name
self.nativePlace = nativePlace
# 【 1 】这里也可以给属性指定默认值
self.school = '武汉理工大学'
def attend_class(self):
return self.name + '正在上课'
# 【 2 】类中的方法,可以增加必要的形参
def attend_class_2(self, address):
return self.name + '正在 ' + address + ' 上课'
def attend_class_3(self, address):
return self.name + '正在 ' + self.school + address + ' 上课'
def finish_class(self):
return self.name + '已经下课'
# 使用类
# 【 3 】根据类创建实例
zhangSan = Student(20200101, '张三', '湖北武汉')
# 【 4 】访问属性
print('创建了一个示例,学生姓名是: ' + zhangSan.name)
# 【 5 】调用方法
print(zhangSan.attend_class())
print(zhangSan.attend_class_2('第一教学楼101教室'))
print(zhangSan.attend_class_3('第一教学楼101教室'))
示例输出:
创建了一个示例,学生姓名是: 张三
张三正在上课
张三正在 第一教学楼101教室 上课
张三正在 武汉理工大学第一教学楼101教室 上课
注:最新的Python中,class关键字后面的类名后边的括号()可以省略
在这个类的使用的示例中,主要有这么几点:
- 【1】 类中的属性可以给指定默认值。
- 【2】类中的方法,可以增加必要的形参。
- 【3】根据类来创建实例的方法如上,即
实例名 = 类名(实参1,实参2……)
。可以创建多个实例。 - 【4】可以直接通过
实例名.属性名
的格式来访问示例的属性。 - 【5】可以直接通过
实例名.方法
的格式来调用示例中的方法,其中有额外参数的需要在调用时给出。
可以对属性的值进行修改,主要有三种方法:
- 直接通过示例进行修改
- 通过方法进行设置
- 通过方法进行递增(即类中的某个方法实现的是递增或自加,可以多次调用这个方法实现对属性的修改。
示例:
# 创建类
class Student:
def __init__(self, no, name, nativePlace):
"""初始化属性no, name, nativePlace"""
self.no = no
self.name = name
self.nativePlace = nativePlace
# 【1】这里也可以给属性指定默认值
self.school = '武汉理工大学'
def attend_class(self):
return self.name + '正在上课'
# 【2】类中的方法,可以增加必要的形参
def attend_class_2(self, address):
return self.name + '正在 ' + address + ' 上课'
def attend_class_3(self, address):
return self.name + '正在 ' + self.school + address + ' 上课'
def finish_class(self):
return self.name + '已经下课'
def setSchool(self, school):
self.school = school
# 这里不仅可以简单的赋值,还可以实现更多功能
# 使用类
liSi = Student(20200102, '李四', '江苏南京')
# 直接通过属性名修改
liSi.school = '南京理工大学'
print(liSi.attend_class_3('第二教学楼102'))
# 通过方法修改属性
liSi.setSchool('华中科技大学')
print(liSi.attend_class_3('第二教学楼103'))
示例输出:
李四正在 南京理工大学第二教学楼102 上课
李四正在 华中科技大学第二教学楼103 上课
3. 继承
编写类时,并非总是要从空白开始。如果要编写的类是另一个现成类的特殊版本,可使用继承。
一个类 继承
另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为 父类
(也叫做 超类(superClass)
) ,而新类称为 子类
。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。
比如,学生都需要上课和下课。在学生这个群体中,有参加学生工作的(如monitor),还有参加志愿服务的(如volunteer)。所以这两类学生,具体普通学生的属性,还有自己的特有属性。那么这两类学生的定义可以采用继承来实现。
可以通过下面这个示例来理解继承的具体使用。
示例:
# 父类
class Student:
# 初始化
def __init__(self, no, name, nativePlace):
self.no = no
self.name = name
self.nativePlace = nativePlace
self.school = '武汉理工大学'
def attend_class(self):
return self.name + '正在上课'
def finish_class(self):
return self.name + '已经下课'
# 【 1 】monitor子类
class Monitor(Student):
# 【 2 】子类初始化
def __init__(self, no, name, nativePlace):
# 【 3 】初始化父类的属性
super().__init__(no, name, nativePlace)
# 【 4 】定义子类属性
self.classRoom = '第五教学楼-107教室'
self.meetingRoom = '321会议室'
# 【 5 】定义子类方法
def attend_A_Meeting(self):
return self.name + ' 正在' + self.meetingRoom + ' 开会'
# 【 6 】重写父类方法
def attend_class(self):
return self.name + ' 正在' + self.school + self.classRoom + ' 上课'
# 使用类
liSi = Monitor(20200103, '李四', '湖北武汉')
print(liSi.attend_A_Meeting())
print(liSi.attend_class())
示例输出:
李四 正在321会议室 开会
李四 正在武汉理工大学第五教学楼-107教室 上课
在这个示例中,对子类的定义主要有这么几点:
- 【1】创建子类是,class关键字后面的子类名后的括号内填写继承的父类名。
- 【2】子类初始化方法的形参,除了包含父类初始化方法的形参外,还可以增加子类独有的形参
- 【3】初始化父类属性的方法如上示例,使用了super()方法,即
super().__init__(父类形参1,父类形参2,……)
。 - 【4】子类独有的属性需要单独定义
- 【5】定义子类自己的方法,根据前述要求定义即可。
- 【6】子类可以对父类的方法进行重写。
另外,可以将一个类的示例,用作另一个类的属性。
4. 导入类
4.1 模块中存储类
在一个模块中,可以存储一个或者多个类。即一个模块可以根据需要,存储任意数量的类。
示例(student.py):
# 父类
class Student:
# 初始化
def __init__(self, no, name, nativePlace):
self.no = no
self.name = name
self.nativePlace = nativePlace
self.school = '武汉理工大学'
def attend_class(self):
return self.name + '正在上课'
def finish_class(self):
return self.name + '已经下课'
# monitor子类
class Monitor(Student):
# 子类初始化
def __init__(self, no, name, nativePlace):
# 初始化父类的属性
super().__init__(no, name, nativePlace)
# 定义子类属性
self.classRoom = '第五教学楼-107教室'
self.meetingRoom = '321会议室'
# 定义子类方法
def attend_A_Meeting(self):
return self.name + ' 正在 ' + self.meetingRoom + ' 开会'
# 重写父类方法
def attend_class(self):
return self.name + '正在' + self.school + self.classRoom + '上课'
# volunteer子类
class Volunteer(Student):
# 子类初始化
def __init__(self, no, name, nativePlace, community):
# 初始化父类的属性
super().__init__(no, name, nativePlace)
# 定义子类属性
self.serviceCommunity = community
# 定义子类方法
def attend_A_Voluntary(self):
return self.name + ' 正在 ' + self.serviceCommunity + ' 志愿服务'
在上面这个模块中,定义了三个类。
4.2 从模块导入类
可以从模块中导入一个类,也可以导入多个类,也可以导入整个模块,也可以导入模块中的所有的类,也可以在一个模块中导入另一个模块。
下面这个示例,展示了如何导入。
示例:
# 导入单个类,并命名别名
from student import Student as Sd
# 导入多个类
from student import Monitor, Volunteer
# 导入全部类
from student import *
# 导入整个模块
import student
示例:
# 导入整个模块
import student
# 使用类
liSi = student.Volunteer(20200104, '李四', '湖北武汉', '余家头社区')
print(liSi.attend_A_Voluntary())
示例输出:
李四 正在 余家头社区 志愿服务
关于模块的导入,有几点建议。
- 一般用到模块中的哪个或者哪几个类,就导入哪个类或者哪几个类。主要是清楚的知道程序使用了哪些类。
- 如果用到了一个模块中的很多类,最好导入整个模块,然后使用
模块名.类名
的形式来访问类。
5. 类的编码风格
- 类名应采用驼峰命名法 ,即将类名中的每个单词的首字母都大写,而不使用下划线。
- 实例名和模块名都采用小写格式,并在单词之间加上下划线。
- 对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。
- 每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。
- 可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。
- 需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import 语句,再添加一个空行,然后编写导入你自己编写的模块的import 语句。包含多条import 语句的程序中,这种做法让人更容易明白程序使用的各个模块都来自何方。
参考文献:
[1] Python编程:从入门到实践
如果有帮助,感谢动动小手点个赞 (๑•̀ㅂ•́)و✧❤