python是一门面向对象的语言,体现面向对象的技术就是类。想要在python编程上进阶,就必须理解和运用类来解决问题。本期的内容难度有所上升,有时间的同学一定要把文中的代码敲一遍,以便加深对类的理解。
为什么需要类?
对于一个学生Jack而言,他的语数英三门成绩分别是88, 85, 94,不难想到用字典{ "Chinese": 88, "Mathemathics": 85, "English": 94 }
来描述。如果要计算他的平均分,需要使用表达式average = sum([Jack[i] for i in Jack])/len(Jack)
来计算。
# 计算Jack同学的平均分
>>> Jack = { "Chinese": 88, "Mathemathics": 85, "English": 94 }
# 使用了列表推导式获取列表[88, 85, 94],对该列表使用sum()方法返回代数和,最后数以科目数,算出平均分
>>> average = sum([Jack[i] for i in Jack])/len(Jack)
>>> print(average)
89.0
# 对于Lucy同学而言,还需要重复Jack的操作
>>> Lucy ={ "Chinese": 92, "Mathemathics": 98, "English": 80 }
>>> average = sum([Lucy[i] for i in Lucy])/len(Lucy)
>>> print(average)
90.0
如果还有一个学生Lucy呢,这么数据和计算平均分的代码又要重新写一遍。我们知道函数的诞生,就是因为要实现单功能的算法代码的复用。那么类的诞生,其实是为了实现复用特定的数据结构和算法。上面的数据和算法,可以用类来改写,实现更高层次的抽象和复用。
# 定义一个Student类
>>> class Student(object):
··· """ Three course of a student, including Chinese, Mathematics and English """
··· def __init__(self, Chinese, Mathematics, English):
··· self.Chinese = Chinese
··· self.Mathematics = Mathematics
··· self.English = English
··· def average(self):
··· return (self.Chinese + self.Mathematics + self.English)/3
···
# Jack是Student类的一个对象,Jack同学的语数英的分数分别是88,85,94
>>> Jack = Student(88, 85, 94)
# 计算Jack同学的平均分,只要直接调用average()方法
>>> Jack.average()
89.0
# 和处理Jack同学的方法类似,Lucy同学也可以作同样的处理
>>> Lucy = Student(92, 98, 80)
>>> Lucy.average()
90.0
虽然只有两名同学的时候,使用类显得更加复杂一点,但是Student类实现了对数据和算法的重用,后面不管再出现多少的同学,我们都可以很轻松地处理,这就是类的魅力所在。
类和对象有什么区别?
有的同学分不清类和对象,简单举个例子:上面的Student就是一个类,而Jack就是类的一个对象,或者叫实例,Lucy是另一个对象。所以我们不难看出:一个类可以有多个对象。从计算机存储的角度讲,类是一个概念,不占用任何存储空间,而对象则是由类所定义的数据组成的,它类似于C语言中的结构体,占用了一定的内存空间。
# Student是一个类,不占用内存空间
>>> Student
<class 'out.Student'>
# Jack是一个对象,它所占用的内存空间是0x0000018C2C3E2358
# 这个内存空间的地址由python解释器分配的,因人而异
>>> Jack
<out.Student object at 0x0000018C2C3E2358>
# 函数也是需要占用内存空间的
>>> Jack.average
<function Student.average at 0x0000018C2C3DB9D8>
怎样创建一个类?
想要创建一个类,必须要了解类的一般形式。下面,我们简单看一下:
class 类名(父类):
""" 类的简介 """
def __init__(self, *args):
代码块
def 函数方法(参数):
代码块
大家不要被它的结构所吓倒,其实拆分开来也很容易理解。
首先,类的标识是class,class后面接类的名称。有的类是别的类的子类,这样的类继承了父类的所有特征。在定义的时候,只要在类名后面的小括号中加上父类的名字,就表明继承父类了。
类的名称下方,一般是类的简介。类的简介一般来说是用引号标注起来的部分。
类一般来说有__init__(self, *args)
方法,它展现了类所包含的数据结构,同时也承担了类数据的初始化的工作。其中,__init__
是专用的方法名称;self
是类的对象实例,它也是专用的名称;*args
是初始化所需要的参数。
# 直接调用Student的average()方法,会提示缺少参数self
>>> Student.average()
TypeError: average() missing 1 required positional argument: 'self'
# 添加参数self,提示self没有定义
>>> Student.average(self)
NameError: name 'self' is not defined
# 添加参数Jack,给出的是89.0的结果
>>> Student.average(Jack)
89.0
# 添加参数Lucy,给出的是89.0的结果
>>> Student.average(Lucy)
90.0
>>> Student.average(Jack) == Jack.average()
True
# 从上面看出,self是Student的某个对象的代称,self可以指代Jack,也可以指代Lucy
除了__init__()
方法以外,类还可以其它方法,这些方法可以帮助我们实现特定的功能。比如:Student类中的average()方法,调用该方法可以算出语数外三门的平均分。
具备了这几个要素,我们就可以创建出一个能发挥作用的类了。
总结
- 类是对数据结构和算法的复用,使用类可以极大地提高编程效率
- 对象是类的具体化,对象占用内存空间和类不占用
- 创建一个类需要考虑:类的名称、父类、简介、初始化、其它方法
思考
# 尝试创建一个类来解决下面的问题:
# Reverse digits of an integer.
# Example1: x = 123, return 321
# Example2: x = -123, return -321
# 本题非聪哥原创,出自leetcode,
# 感兴趣的同学可以去这个网站看看,由很多考验水平的算法题哦 ^_^
# 原题链接:https://leetcode.com/problems/reverse-integer/#/description
扫一扫这个二维码,关注公众号:聪哥python,获取最新python3基础教程