第1课 数据抽象类与Python类¶
Python中的基本数据类型¶
在每种编程语言中都会内置一些基本的数据类型供程序设计者使用。在Python中,同样内置了若干种数据类型。我们常用的内置数据类型有九种,这九种基本类型大致可以分为两类:基本类型 和 组合类型。基本类型一般指单一的数据类型,也可以称做原始数据类型(Primitive Type)。而组合类型则可以简单地理解成由基本类型组合而成的数据类型。
在Python中,使用type(variable)
内置函数,可以查看变量的数据类型。
-
基本类型
str
字符串int
整数型float
浮点型bool
布尔变量
-
组合类型
bytes
字节类型tuple
元组类型set
集合类型dictionary
字典类型list
列表类型
抽象数据类型(Abstract Data Type)¶
抽象数据类型的意义:¶
显然,光用以上的内置数据类型去解决现实生活中的问题是远远不够的。世界如此丰富多彩,那我们如何才能利用计算机去描述万事万物,解决现实问题呢?
在上学期中,我们学习了Python的基本语法(的一点点),学习程序设计中的基本流程控制:顺序结构、分支结构和循环结构。可以说完成了世界万事万物运行的流程的抽象。而在数据层面上,也需要将它抽象出来。
抽象数据类型 就是指一个数据元素集合以及在这些数据上的操作。我们要注意,抽象数据类型的定义与实现是分开的。首先我们要研究他的结构和定义,而非考虑他是如何实现的细节。只要将一种抽象数据类型定义完成,其可以用任何工具实现,所以在这个阶段是不考虑他具体是如何实现的。
抽象数据类型的表示方法¶
在描述一个抽象数据类型时,我们可以使用预先定义好的数据类型(比如:Python中已经定义好的数据类型:int
, str
, bool
, float
以及其他类型)来定义抽象数据类型。
在本课中,我们使用不严格的定义方法:
抽象数据类型名{
数据:
预定义好的数据类型组合
操作:
抽象数据类型的操作
}
例如:一个二维平面中的点的抽象数据类型的定义为:
ADT Point {
数据:
x: float # 定义横坐标
y: float # 定义纵坐标
操作:
distance(p: Point) -> float # 计算当前点到给定点p距离
}
例如:我们可以定义一个学生类型
ADT Student {
数据:
name: str # 学生姓名
age: int # 学生年龄
grade: int # 年级
courses: list[str] # 选修课程列表
操作:
grow() # 增长1岁
grade_up() # 年级升高1年
sign_up_for(course: str) # 添加选修课程
...
}
再举1个例子,我们在上学期经常会遇到的例子,就是游戏中的Player。当时我们使用了dict
来实现,现在有了抽象数据类,我们能更好定义Player这个数据抽象类。很快可以得出以下定义:
ADT Player {
数据:
name: str # 玩家姓名
mp: int # 魔法值
hp: int # 健康值
level: int # 级别
ep: int # 经验值
weapons: list[str] # 武器列表
equipments: list[str] # 装备列表
操作:
attack(p: Player) # 攻击另一位玩家p
level_up() # 升级
poison(t: int) # 中毒t秒
pick_up(weapon: str) # 装备weapon
drop(weapon: str): # 扔掉装备
...
}
Python语言中的class
¶
Python语言中,可以使用class
来完成抽象数据类的定义与实现。
基本语法¶
Python语言中class的基本语法为:
class ADTName:
def __init__(self, field1, field2...):
# 在这里初始化类的属性、字段(Properties, Fields)
self.field1 = field1
slef.field2 = field2
...
# 成员函数(member functions)或者方法(methods)
def action1(self, params...):
# function body
def action2(self, params...):
# function body
Python Class¶
Class & Objects¶
类是用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。
当类进行实例化后就会产生一个对象。对于前面我们实现的Student类,那么我们可以实例化出不同的对象:张三、李四等。如下图所示:
下面给出了抽象数据类Student的Python实现版本:
class Student:
def __init__(self, name, age, grade, courses):
self.name = name
self.age = age
self.grade = grade
self.courses = courses
def grow(self): # 增长1岁
self.age += 1
def grade_up(self): # 年级升高1年
self.grade += 1
def sign_up_for(self, course: str): # 添加选修课程
if course not in self.courses:
self.courses.append(course)
类构造(Construct)/初始化(Initialization)¶
Python中的类的构造函数是指在Python实例化时会调用的函数。他的主要工作是对对象内部的数据进行初始化的工作。他是一个特殊的函数,他由双下划线包裹着单词init构成。注意:这里的第一个参数是self
, 用于指代对象本身。在下面我们可以看到,类中的方法(成员函数)都需要使用self
做为第一个参数。
通常在python的构造函数中,要将所有数据都进行初始化。如下:
class Dog:
def __init__(self, color: str, price: float):
self.color = color
self.price = price
定义好__init__
函数后,我们就可以生成实例化对象了。下面的语句生成了两个不同的Dog
对象,一个对象颜色为白色, 价钱为2000,另一个颜色的对象为黑色,价钱为100。
white_dog = Dog("white", 2000)
black_dog = Dog("black", 100)

属性(Properties)¶
前面提到过,在类初始化的过程中,初始化了很多对象内的数据,在Python中一般称为属性。当对象建立后,可以使用obj.property
的方式访问对象中的属性。
print("The color of the first dog is {}.".format(white_dog.color))
print("The price of the second is {}.".format(black_dog.color))
方法(Methods)¶
在类中的方法大多时候为对象的方法。定义方法时,需要将函数的第一个参数设为self
, 表明在实际对象调用该方法时,会将实例对象当做self
传进函数中。这时就可以使用如self.color
等方式访问和修改对象当中的实例了。
如果你不把方法的第一个参数设置为self
,那么就无法使用对象后的实例访问这个方法。而变成了一个 类方法。这种情况可以使用: 类名.方法()
方式进行调用。如下面的例子:
class A:
def method_a():
print("This is a method from class")
def method_b(self):
print("This is a method from instance")
a = A()
a.method_a()
a.method_b()
A.method_a()
完整的示例¶
Point and Circle¶
import math
class Point:
def __init__(self, x: float, y: float):
self.x = x # 横坐标
self.y = y # 纵坐标
def distance(self, p: Point) -> float:
return math.sqrt( (self.x - p.x) ** 2 + (self.y - p.y) ** 2)
class Circle:
def __init__(self, center: Point, radius: float):
self.center = center
self.radius = radius
def area(self) -> float:
return math.pi * self.radius * self.radius
def is_tangent_to(self, circle: Circle) -> bool:
return self.center.distance(circle.center) == self.radius + circle.radius
日期类¶
class Date:
def __init__(self, year: int, month: int, day: int):
self.year = year
self.month = month
self.day = day
def is_leap_year(self):
return (self.year % 100 == 0 and self.year % 400 == 0) or (self.year % 100 != 0 and self.year % 4 == 0)
def caculate_days_between(self, another_date: Date) -> int:
# include end date in calculation.
# homework
作业¶
完成OJ系统中的 C001、C002 两题。