该部分为学习笔记,具体内容详见:《数据结构(Python语言描述)》一书
第1章 Python语言程序设计基础
第一节 Python基础知识
一、Python概述及运行环境
Anaconda + PyCharm + Python 3.6
二、Python的变量和数据类型
- 数值型
- 整型(int)
- 浮点型(float)
- 复数型(complex)
- 布尔型(bool)
- 字符串
方 法 | 说 明 |
---|---|
string.count() | 返回字符串指定子串出现的次数 |
string.endswith() | 检查字符串是否以指定字符串结束 |
string.find() | 查找子串,如果存在返回开始的索引值,否则返回-1 |
string.index() | 和find()方法一样,但如果子串不存在将会出现一个异常 |
string.isalnum() | 如果 string 的所有字符都是字母或数字,返回 True,否则返回 False |
string.isalpha() | 如果 string 的所有字符都是字母,返回 True,否则返回 False |
string.isdecimal() | 如果 string 只包含十进制数字,返回 True,否则返回 False |
string.isdigit() | 如果 string 只包含数字,返回 True,否则返回 False |
string.isnumeric() | 如果 string 只包含数字字符,返回 True,否则返回 False |
string.isspace() | 如果 string 只包含空格,返回 True,否则返回 False |
string.join() | 拼接字符串 |
string.lower() | 转换 string 的所有大写字符为小写 |
string.replace() | 字符串替换 |
string.rfind() | 类似于 find() 方法,但是从右边开始查找 |
string.rindex() | 类似于 index() 方法,但是从右边开始查找 |
string.split() | 拆开字符串 |
string.startswith() | 检查字符串是否以指定字符串开头 |
string.title() | 将所有单词转换为以大写开始,其余字母均为小写 |
string.upper() | 转换 string 的小写字母为大写 |
- 列表
·
| 函 数 |说 明 |
|:--------😐:-------------😐
| len() | 返回列表元素的个数 |
| list() | 将其他序列转换为列表 |
| max() | 返回列表元素的最大值 |
| min() | 返回列表元素的最小值 |
| sorted() | 返回排序的结果· |
方 法 | 说 明 |
---|---|
list.append() | 在列表末尾添加新的对象 |
list.clear() | 清空列表 |
list.copy() | 复制列表 |
list.count() | 统计某个元素在列表中出现的次数 |
list.extend() | 在列表末尾扩展某个列表中的所有元素 |
list.index() | 从列表中找出某个值第一个匹配项的索引位置 |
list.insert() | 将对象插入列表指定的位置 |
list.pop() | 删除列表中的一个元素(默认最后一个元素),且返回该元素的值 |
list.remove() | 基于值删除列表中的第一个匹配项 |
list.reverse() | 逆序列表中的元素 |
list.sort() | 对列表进行排序 |
注:Python中列表的赋值默认是浅拷贝,也就是说修改了 lst2 就是修改了 lst1。 如果需要实现二者的独立存储,可以使用 list.copy()。
- 元组
元组可以看做不可以修改的列表,可以认为元组所能完成的功能用列表一定可以做到。但是站在程序设计数据安全的角度,在有些场合中数据的不可修改性非常重要,这些场合选用元组将会降低因为误修改数据而导致程序逻辑错误的可能性。 - 集合
上述字符串、列表和元组都是有序的序列,而集合是偶一个无序的且无重复元素的序列,因此集合非常适用于去除重复项。
方 法 | 说 明 |
---|---|
add() | 为集合添加元素 |
clear() | 清除集合的所有元素 |
copy() | 产生集合的一个副本 |
difference() | 返回多个集合的差集 |
discard() | 删除集合指定的元素,如果不存在就放弃 |
intersection() | 返回集合的交集 |
isdisjoint() | 判断两个集合是否包含相同的元素 |
issubset() | 判断指定集合是否为该方法参数集合的子集 |
issuperset() | 判断指定集合是否为该方法参数集合的超集 |
remove() | 删除指定元素,如果不存在就抛出异常 |
symmetric_difference() | 返回两个集合不重复的元素集合 |
union() | 返回两个集合的并集 |
update() | 给集合添加元素或集合 |
- 字典
上述列表、元组和字符串都是用证书作为索引来访问元素,而字典可以用关键字作为索引。与集合一样,字典中的数据对于 Python 程序员而言是无序的。
方 法 | 说 明 |
---|---|
clear() | 删除字典内的所有元素 |
copy() | 返回字典的一个副本 |
fromkeys() | 基于现有的序列创建一个新字典 |
get() | 返回指定键的值,如果值不在字典中,则返回指定的默认值 |
items() | 以列表返回可遍历的(键,值) |
keys() | 返回所有的键 |
update() | 合并指定字典的项到当前字典 |
values() | 返回所有的值 |
pop() | 删除字典中指定键所在的项,并返回该项的值 |
has_key() | 判断指定的键在字典中是否存在 |
三、Python的运算符
- 算术运算符:+, -, *, /, %, **, //
- 关系运算符:>, <, >=, <=, ==, !=
- 逻辑运算符:and, or, not
- 简单赋值运算符:=
- 位运算符:&, |, ~, ^, <<, >>
- 成员资格运算符:in, not in
- 身份运算符:is, is not
四、函数
- 函数的定义
- 函数的返回值
- 函数的调用
- 常用的内置函数
方 法 | 说 明 |
---|---|
bin() | 返回数字转二进制的结果字符串 |
chr() | 返回内码所对应的字符 |
eval() | 计算表达式的值 |
help() | 返回指定模块或者函数的说明文档 |
hex() | 返回数字转十六进制的记过字符串 |
id() | 返回对象的内存地址 |
isinstance() | 判断一个对象是否指定类的实例 |
map() | 返回对指定序列映射后的迭代器 |
ord() | 返回字符的内码,对于西文而言就是ASCII码 |
range() | 返回一个可迭代对象 |
type() | 返回对象的类型 |
五、输入、输出和文件
- 输入和输出:input(),print()
- 文件:open(file, mode = ‘r’, buffering = -1, encoding = None)
模 式 | 说 明 |
---|---|
b | 以二进制格式打开文件 |
r | 以二进制格式打开文本文件 |
rb | 以二进制格式打开一个文件用于只读 |
r+ | 打开一个文件用于读/写 |
rb+ | 以二进制格式打开一个文件用于读/写 |
w | 打开一个文件只用于写入。如果该文件已存在则打开文件(原有内容会被删除),否则创建新文件 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件(原有内容会被删除),否则创建新文件 |
w+ | 打开一个文件用于读/写。如果该文件已存在则打开文件(原有内容会被删除),否则创建新文件 |
wb+ | 以二进制格式打开一个文件用于读/写。如果该文件已存在则打开文件(原有 内容会被删除),否则创建新文件 |
a | 打开一个文件用于追加。 如果该文件已存在则打开文件并定位文件指针到文件结尾,否则创建新文件 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在则打开文件并定位文件指针到文件结尾,否则创建新文件 |
a+ | 打开一个文件用于读/写。如果该文件已存在则打开文件并定位文件指针到文件结尾,否则创建新文件 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在则打开文件并定位文件指针到文件结尾,否则创建新文件 |
方 法 | 说 明 |
---|---|
close() | 关闭文件 |
flush() | 强制把内部缓冲区中的数据立刻写入文件 |
read() | 从文件读取指定的字节数,如果为空或为负则读取所有 |
readline() | 读取一行 |
readlines() | 读取所有行并返回列表 |
seek() | 移动文件读取指针到指定位置 |
tell() | 返回文件当前位置 |
write() | 将字符串写入文件 |
writelines() | 向文件写入列表中的所有数据 |
六、异常处理
- Python与异常
- try:监视异常
- raise:抛出异常
- except:和异常类型相结合可以捕获指定类型的异常
- finally:异常处理的收尾和善后操作
- else:不仅可以用于循环中,还可以用于异常处理
- 异常处理器:由 try 和 except 组成的代码被称为异常处理器,一个异常处理可以包含一个 try 和多个 except。
- 错误与异常处理原则
- 程序遇到错误情况时,如果还能以某种方式执行下去,不要随意终止执行,不轻易崩溃。
- 在遇到错误时,不出现任意的非预期行为,任何时候的行为都应该符合预期。
- 当某个局部发生错误时尽可能局部处理。
七、模块
- 导入模块
- 安装第三方包
功 能 | 命 令 |
---|---|
显示版本 | pip --version |
查看帮助 | pip -help |
安装包 | pip install 包名 |
安装指定版本的包 | pip install 包名 == 版本号 |
升级包 | pip install -u 包名 |
显示包的信息 | pip show 包名 |
列出已经安装的包 | pip list |
查看可以升级的包 | pip list -o |
搜索包 | pip search 包名 |
卸载包 | pip uninstall 包名 |
- 创建自定义模块
模块本质上就是一个 py 文件,在进行程序开发时应将程序分成多个模块,这样不仅结构清晰而且方便管理。每个模块不仅可以自己运行,也可以被导入其他模块中调用。
第二节 Python 面向对象编程
一、面向对象的基本概念
- 类:具有相同属性和方法的对象的集合。
- 对象:对象是类的实例,类和对象是抽象和具体的关系,一个类可以产生多个实例。
- 方法:类中的函数被称为方法,方法是类的动态特性,方法也被称为函数成员。
- 属性:类中的变量被称为属性,属性是类的静态特性,属性也被称为数据成员。
二、类的定义和使用
- self 参数:类的成员函数必须有一个 self 参数。因为类的成员函数是本类的所有对象共享的,每个对象在调用成员函数时自动把自身传递过来,因此通过 self 可以得到调用成员的当前对象。
- 类变量:类变量定义在类内部有但又在类的成员函数之外,它是类的所有对象共享的、公用的。也就是说,如果一个类有一个类变量,该类无论产生多少个对象,它们的此类变量只有一份,是大家公用的。
- 实例变量:实例变量是每个实例独有的,每个对象的实例变量互不影响。如果一个类有一个实例变量,该类产生了 n 个对象,就有 n 份此实例变量。
- 成员的权限:类中的成员可以有3种权限,即公有、私有和保护。Python是依靠成员的名称来区分3种权限的。如果以两个下划线开头表示是私有成员,如果以一个下划线开头表示的是保护成员,否则就是公有成员。
- __init__ 方法:是类的一个特殊方法,被称为类的构造方法。没当用类产生对象时都会自动调用此方法,因此它非常适合用于初始化数据成员。
- 类的实例化以及访问成员:用类产生对象的过程就是类的实例化过程。在类的外部可以通过“对象名.成员名”的方式访问类的公有成员。类变量是属于类的,所以对象是共享的,因此也可以通过“类名.成员”的方式来访问公有类变量。
三、继承与派生
类的第一个作用是产生对象,第二个作用是作为基类进行继承和派生。Python 不仅支持单一继承,还支持多重继承。
四、迭代器与生成器
- 迭代器:是一个可以遍历而且自己记录遍历位置的对象。它的工作模式属于“懒惰模式”,也就是在调用迭代器时才会返回下一个元素。
- 生成器:生成器也是可以迭代的,但它不用实现 __iter__ 和 __next__ 方法,只需要使用关键字 yield。
第三节 与数据结构和算法相关的Python模块
一、抽象基类和abc模块
类通常有两个作用,分别是产生对象和作为基类。如果一个类不能产生对象,他们这个类被称为抽象类。抽象类只能作为基类,最大的作用是使子孙类都有所希望的方法,从而使调用者可以规范、统一地调用处理子孙类的方法。
import abc
class animal(metaclass = abc.ABCMeta)
@abc.abstractmethod
def sound(self):
pass
class dog(animal):
def sound(self):
print("汪汪汪")
class cat(animal):
def sound(self):
print("喵喵喵")
class duck(animal):
def sound(self):
print("嘎嘎嘎")
def playSound(temp):
temp.sound()
dog1 = dog()
cat1 = cat()
duck1 = duck()
playSound(dog1)
playSound(cat1)
playSound(duck1)
二、ctypes模块
Python 的 ctypes 模块提供了一系列与 C、C++语言兼容的数据结构类与方法,可以调用 C 源代码编译得到的动态链接库,从而实现 Python 程序与 C 程序之间的数据交换与调用。
三、array模块
它是一种高效的数组存储类型,所有的数组成员必须是同一种类型,在创建数组的时候就需要确定数组的类型。
四、NumPy模块
NumPy 是 Python 的一个扩展程序库,支持大数组与大型矩阵运算,并提供了大量的数学函数库。它本身用 C 语言实现,把上层提供的数据类型和操作推到底层执行,效率非常高。
五、collections模块
在 Python 内置数据类型的基础上, collections 模块还提供了额外的数据类型,这些数据类型实现精良、运行效率高,熟练掌握有时可以达到事半功倍的效果。如:
- counter:计数器,统计可哈希的对象
- OrderedDict:有序字典
- Defaultdict:带有默认值的字典
- Namedtuple:可以用名字访问元素内容的元组
- Deque:双端队列
- ChainMap:统一多映射视图的字典
第四节 上机实验
一、找零钱
编写一个“找零钱”的 Python 程序。程序应该输入两个数字,一个表示商品价格,一个表示客户支付的欠款。当客户支付的钱款大于商品价格时,它应该返回用于找零的纸币和硬币的数量。纸币和硬币的面值可以基于中国现阶段的货币体系。试设计程序,以便返回尽可能少的纸币和硬币。
二、数列面向对象练习
设计一个数列类,并以此为父类派生出它的 3 个子类,即等差数列类、等比数列类和斐波那契数列类。4 个类的作用如下:
(1)数列类是父类,该类的对象可以产生从指定数值 start 开始增量为 1 的数列。
(2)等差数列类是数列类的派生类,用于产生从指定数值 start 开始增量为 increment 的数列。
(3)等比数列类是数列类的派生类,用于产生从 start 开始基数为 base 的数列。
(4)斐波那契数列类也是数列类的派生类,用于产生从 first 和 second 开始的斐波那契数列。
- 将父类设计为迭代器类,因此需要实现__next__和__iter__方法。此外,父类需要提供构造函数__init__、输出方法(可指定输出多少个数)和计算下一个值的_advance 方法。
- 各子类仅包含构造函数和_advance 方法,它们的构造函数可通过调用父类的构造函数及加入子类特有的语句进行初始化,子类的 _advance 方法提供了各自不同的实现以生成下一个元素。