Python基础

第〇章 PYTHON简介

0.1 Python简介

Python时当前比较流行的编程语言。具有简单易学、免费开源、应用领域广泛等特点。

0.2 计算机的组成

本节课重点关注CPU内存的作用。其中内存是临时存储数据的地方,由于内存的速度远远高于硬盘,所以CPU处理的数据都是从内存调取的。

0.3 Python学习路径

第一章 PYTHON入门基础

1.1 解释器的作用和分类

(一) 解释器的作用

Python解释器的作用:运行文件。(形象化类比人类翻译官,解释器就是将python语句“翻译为”计算机能读懂的机器码)。

(二) 解释器的种类
  • CPython:C语言开发的解释器【官方】,应用广泛的解释器;
  • IPython:基于CPython的一种交互式解释器;
  • 其他解释器
    • PyPy:基于Python语⾔言开发的解释器器;
    • Jython:运行在Java平台的解释器器,直接把Python代码编译成Java字节码执行;
    • IronPython:运行在微软.Net平台上的Python解释器器,可以直接把Python代码编译
      成.Net的字节码。

1.2 下载Python解释器

安装了andaconda好像就不用单独安装解释器了。

1.3 PyCharm的应用

(一) PyCharm简介

PyCharm是一种Python IDE(集成开发环境),带有一整套可以帮助用户在使用Python语⾔言开发时提高其效率的工具,内部集成的功能有Project管理,智能提示,语法高亮,代码跳转,调试代码,解释代码(解释器),框架和库等等。

(二) PyCharm设置

(1) 界面设置

(2) 设置解释器

(3) 项目管理

1.4 注释

注释分为两类:单行注释和多行注释

  • 单行注释(快捷键:ctrl+/)
1
# 注释内容
  • 多行注释
1
2
3
4
5
6
7
8
"""
多行注释1
多行注释2
"""
'''
多行1
多行2
'''

1.5 变量

(一) 定义变量
1
变量名 = 值

要注意,变量名的命名要符合标识符命名规则

  • 由数字、字母、下划线组成
  • 不能数字开头
  • 不能使用内置关键字
  • 严格区分大小写
(二) 命名习惯
  • 见名知义。
  • 大驼峰:即每个单词⾸首字⺟母都⼤大写,例如: MyName 。
  • 小驼峰:第二个(含)以后的单词首字母大写,例如: myName 。
  • 下划线:例如: my_name 。

1.6 Bug问题

所谓bug,就是程序中的错误。如果程序有错误,需要程序员排查问题,纠正错误。

(一) Debug工具——调试

(1) 步骤1:打断点

单击目标代码的行号右侧空白位置。

(2) 步骤2:调试

打成功断点后,在文件内部任意位置 — 右键 — Debug’文件名’ — 即可调出Debug工具⾯面板 — 单击Step
Over/F8,即可按步执行行代码。

  • Debugger

​ 显示变量量和变量量的细节

  • Console

​ 输出内容

1.7 数据类型

产看变量的类型使用type

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
a = 1
print(type(a)) # <class 'int'> -- 整型
b = 1.1
print(type(b)) # <class 'float'> -- 浮点型
c = True
print(type(c)) # <class 'bool'> -- 布尔型
d = '12345'
print(type(d)) # <class 'str'> -- 字符串
e = [10, 20, 30]
print(type(e)) # <class 'list'> -- 列表
f = (10, 20, 30)
print(type(f)) # <class 'tuple'> -- 元组
h = {10, 20, 30}
print(type(h)) # <class 'set'> -- 集合
g = {'name': 'TOM', 'age': 20}
print(type(g)) # <class 'dict'> -- 字典

1.8 输出

(一) 认识格式化符号
  • 格式化输出
    • 格式化符号
    • f-字符串串
  • print的结束符
(二) 格式化输出

(1) 常见格式化符号

格式符号 转换
%s 字符串
%d 有符号的十进制整数
%f 浮点数

技巧:

%06d,表示输出的整数显示位数,不足以0补全,超出当前位数则原样输出;
%.2f,表示小数点后显示的小数位数。

(2) 格式化输出示例

格式化字符串除了%s,还可以写为f'{表达式}'(是Python3.6中新增的格式化方法,该方法更简单易读。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
age = 18
name = 'TOM'
weight = 75.5
student_id = 1

# 我的名字是TOM
print('我的名字是%s' % name)

# 我的学号是0001
print('我的学号是%04d' % student_id)

# 我的体重是75.50公斤
print('我的体重是%.2f公斤' % weight)

# 我的名字是TOM,今年年18岁了
print('我的名字是%s,今年%d岁了' % (name, age))

# 我的名字是TOM,明年年19岁了了
print('我的名字是%s,明年%d岁了' % (name, age + 1))

# 我的名字是TOM,明年年19岁了了
print(f'我的名字是{name}, 明年{age + 1}岁了')

注意,其中%s的功能相对更强,可以格式化输出字符串、整数、浮点数。

(三) 转义字符
  • \n:换行
  • \t:制表位,一个tab键(4个空格距离)
(四) 结束符

想⼀想,为什么两个print会换行输出?

1
2
3
print('输出的内容', end="\n")
# 修改结束符号为...
print('输出的内容', end="...")

在Python中,print(), 默认自带end=”\n” 这个换行行结束符,所以导致每两个print 直接会换⾏行行
展示,用户可以按需求更改结束符。

1.9 输入

(一) 输入语法

在Python中,程序接收用户输入的数据的功能即是输入。

1
变量 = input("提示信息")
(二) 输入的特点
  • 当程序执行到input ,等待用户输入,输入完成之后才继续向下执行;
  • 在Python中, input 接收用户输入后,一般存储到变量,方便使用;
  • 在Python中, input 会把接收到的任意用户输入的数据都当做字符串处理。
(三) 演示输入
1
2
3
4
password = input('请输⼊入您的密码:')
print(f'您输⼊入的密码是{password}')
# <class 'str'>
print(type(password))

1.10 数据类型转换

(一) 转换数据类型的作用

问:input()接收⽤用户输入的数据都是字符串类型,如果用户输入1,想得到整型该如何操作?
答:转换数据类型即可,即将字符串类型转换成整型。

(二) 转换数据类型的函数
函数 说明
int(x[,base]) 将x转换为一个整数
float(x) 将x转换为一个浮点数
str(x) 将对象 x 转换为字符串
tuple(s) 将序列列 s 转换为一个元组
list(s) 将序列列 s 转换为一个列表
eval(str) 用来计算在字符串中的有效Python表达式,并返回一个对象
complex(real [,imag ]) 创建一个复数,real为实部,imag为虚部

1.11 运算符的分类

  • 算数运算符
  • 赋值运算符
  • 复合赋值运算符
  • 比较运算符
  • 逻辑运算符
(一) 算术运算符
运算符 描述 实例
+
-
*
/
// 整除 9 // 4 输出结果为 2
% 取余 9 % 4 输出结果为 1
** 指数 2 * 4 输出结果为 16,即 2 2 2 2
() 括号 小括号⽤用来提高运算优先级,即 (1 + 2) * 3 输出结果为 9
(二) 赋值运算符
运算符 描述 实例
= 赋值 将= 右侧的结果赋值给等号左侧的变量
1
2
3
4
5
6
7
8
9
10
# 多变量赋值
num1, float1, str1 = 10, 0.5, 'hello world'
print(num1)
print(float1)
print(str1)

# 多变量量赋相同值
a = b = 10
print(a)
print(b)
(三) 复合赋值运算符
运算符 描述 实例
+= 加法赋值运算 c += a 等价于 c = c + a
-= 减法赋值运算 c -= a 等价于 c = c - a
*= 乘法赋值运算 c = a 等价于 c = c a
/= 除法赋值运算 c /= a 等价于 c = c / a
//= 整除赋值运算 c //= a 等价于 c = c // a
%= 取余赋值运算 c %= a 等价于 c = c % a
**= 指数赋值运算
(四) 关系/比较运算符
运算符 描述 实例
== 相等
!= 不相等
> 大于
>= 大于等于
< 小于
<= 小于等于
(五) 逻辑运算符
运算符 逻辑表达式 描述 实例
and x and y 布尔”与”:若x为False,x and y返回False,否则返回y值 True and False,返回False
or x or y 布尔”或”:若x是True,返回 True,否则返回y的值 False or True,返回True
not not x 布尔”非”:若x为True,返回False 。若x为False,返回 True not True 返回 False
(六) 小结
  • 算数运算的优先级
    • 混合运算优先级顺序: () 高于 * 高于 / // % 高于 + -

第二章 流程控制

2.1 条件语句

条件语句,即条件成立执行某些代码,条件不成立则不执行这些代码。

(一) if语句语法
1
2
3
4
if 条件:
条件成立执行的代码1
条件成立执行的代码2
......
(二) if-else语句语法

作用:条件成立执行if下方的代码; 条件不成立执行else下方的代码。

1
2
3
4
5
6
7
8
if 条件:
条件成立执行的代码1
条件成立执行的代码2
......
else:
条件不成立执行的代码1
条件不成立执行的代码2
......
(三) 多重判断:if-elif-else语句语法
1
2
3
4
5
6
7
8
9
10
11
12
13
if 条件1:
条件1成立执行的代码1
条件1成立执行的代码2
......
elif 条件2
条件2成立执行的代码1
条件2成立执行的代码2
......
elif 条件3:
......
......
else:
以上条件都不成立执行的代码
(四) if嵌套语法
1
2
3
4
5
6
7
if 条件1
条件1成立执行的代码
条件1成立执行的代码

if 条件2
条件2成立执行的代码
条件2成立执行的代码
(五) 示例——猜拳游戏
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
"""
提示:0-石头,1-剪刀,2-布
1. 出拳
玩家输入出拳
电脑随机出拳

2. 判断输赢
玩家获胜
平局
电脑获胜
"""

# 导入random模块
import random
# 计算电脑出拳的随机数字
computer = random.randint(0, 2)
print(computer)
player = int(input('请出拳:0-石头,1-剪刀,2-布:'))
# 玩家胜利 p0:c1 或 p1:c2 或 p2:c0
if ((player == 0) and (computer == 1) or ((player == 1) and (computer == 2) or
((player == 2) and (computer == 0)):
print('玩家获胜')
# 平局:玩家 == 电脑
elif player == computer:
print('平局')
else:
print('电脑获胜')
(六) 三元运算符

三元运算符也叫三目运算符或三元表达式。

1
条件成立执行的表达式 if 条件 else 条件不成立执行的表达式

示例:

1
2
3
4
a = 1
b = 2
c = a if a > b else b
print(c) # 输出c=b=2

2.2 循环语句

(一) 循环语句的分类

在Python中,循环分为while和for两种,最终实现效果相同。

(二) while循环的语法
1
2
3
4
while 条件:
条件成立重复执行的代码1
条件成立重复执行的代码2
......

示例:计算1-100累加和

1
2
3
4
5
6
7
i = 1
result = 0
while i <= 100:
result += i
i += 1
# 输出5050
print(result)
(三) while循环嵌套

略。。。

(四) for循环的语法
1
2
3
4
for 临时变量 in 序列:
重复执行的代码1
重复执行的代码2
......
(五) 循环与else

循环和else配合使用,else下方缩进的代码指的是当循环正常结束之后要执行的代码。

所谓else指的是循环正常结束之后要执行的代码,即如果是break终止循环的情况,else下方缩进的代码将不执行,但是对于continue语句则else正常执行。

(1) while…else

1
2
3
4
while 条件:
条件成立重复执行的代码
else:
循环正常结束之后要执行的代码

(2) for…else

1
2
3
4
5
for 临时变量量 in 序列列:
重复执行的代码
...
else:
循环正常结束之后要执行的代码
(六) 退出循环的两种方式——break、continue

break和continue是循环中满足一定条件退出循环的两种不同方式。

  • break控制循环流程,即终止此循环,跳出循环
  • continue控制循环流程,即退出当前一次循环继而执行下一次循环,不跳出循环

第三章 数据类型

Python 序列、列表(List)、元组(Tuple):序列是Python中最基本的数据结构,主要包括有:字符串、列表、元组。序列,顾名思义,是有序的,序列都有索引,都能进行索引、切片(截取)、加(连接)、乘(倍增)、检查成员的操作。因为序列有序,可通过位置来区分元素,所以序列中可含有相同的元素。

3.1 字符串

(一) 认识字符串

字符串是 Python 中最常用的数据类型。我们一般使用单/双/三引号来创建字符串。创建字符串很简单,只要为变量分配一个值即可。

1
2
3
4
5
6
7
8
name1 = 'Tom'
name2 = "Rose"
name3 = ''' Tom '''
name4 = """ Rose """
a = ''' i am Tom,
nice to meet you! '''
b = """ i am Rose,
nice to meet you! """

两个注意事项:

  • 注意1:三引号形式的字符串支持换行
  • 注意2:用单引号创建一个带有单引号的字符串I’m Tom需要使用反斜杠进行转义,e.g.'I\'m Tom',但是用双引号就不需要,e.g."I'm Tom"
(二) 字符串的下标索引

“下标” 又叫“索引” ,就是编号。比如火车座位号,座位号的作用:按照编号快速找到对应的座位。同
理,下标的作用即是通过下标快速找到对应的数据。

  • python中对字符串的下标索引使用[]完成
  • 字符串下标从0开始
  • 可以使用负号索引
1
2
3
4
name = "abcdef"
print(name[1]) # b
print(name[0]) # a
print(name[-1]) # f
(三) 字符串切片操作

切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作。

(1) 语法

1
序列[开始位置下标:结束位置下标:步长]

注意

  1. 不包含结束位置下标对应的数据(即左闭右开区间), 正负整数均可;
  2. 步长是选取间隔,正负整数均可,默认步长为1。
1
2
3
4
5
name = "abcdefg"
print(name[2:5:1]) # cde
print(name[2:5]) # cde
print(name[:-1]) # abcdef, 负1表示倒数第⼀一个数据
print(name[-4:-1]) # def
(四) 字符串查找操作

所谓字符串查找方法即是查找子串在字符串中的位置或出现的次数。

(1) find函数

find():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则返回-1。

1
字符串序列.find(子串, 开始位置下标, 结束位置下标)

示例

1
2
3
4
5
mystr = "hello world and itcast and itheima and Python"

print(mystr.find('and')) # 12
print(mystr.find('and', 15, 30)) # 23
print(mystr.find('ands')) # -1

注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。

(2) index函数

index():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则报异常。

1
字符串序列.index(子串, 开始位置下标, 结束位置下标)

示例

1
2
3
4
5
mystr = "hello world and itcast and itheima and Python"

print(mystr.index('and')) # 12
print(mystr.index('and', 15, 30)) # 23
print(mystr.index('ands')) # 报错

注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。

(3) rfind、rindex函数

rfind(): 和find()功能相同,但查找方向为右侧开始。
rindex():和index()功能相同,但查找方向为右侧开始。

(4) count函数

count():返回某个子串在字符串中出现的次数。

1
字符串序列.count(子串, 开始位置下标, 结束位置下标)

示例

1
2
3
4
5
mystr = "hello world and itcast and itheima and Python"

print(mystr.count('and')) # 3
print(mystr.count('ands')) # 0
print(mystr.count('and', 0, 20)) # 1

注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。

(五) 字符串修改操作

所谓修改字符串,指的就是通过函数的形式修改字符串中的数据。

(1) replace函数

replace():替换字符串

1
字符串序列.replace(旧子串, 新子串, 替换次数)

注意:替换次数如果查出子串出现次数,则替换次数为该子串出现次数。

示例

1
2
3
4
5
6
7
8
9
10
mystr = "hello world and itcast and itheima and Python"

print(mystr.replace('and', 'he'))
# 结果:hello world he itcast he itheima he Python

print(mystr.replace('and', 'he', 10))
# 结果:hello world he itcast he itheima he Python

print(mystr)
# 结果:hello world and itcast and itheima and Python

注意:数据按照是否能直接修改分为可变类型不可变类型两种。字符串类型的数据修改的时候不能改变原有字符串,属于不能直接修改数据的类型即是不可变类型。

(2) split函数

split():按照指定字符分割字符串。

1
字符串序列.split(分割字符, num)

注意:num表示的是分割字符出现的次数,即将来返回数据个数为num+1个。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
mystr = "hello world and itcast and itheima and Python"

print(mystr.split('and'))
# 结果:['hello world ', ' itcast ', ' itheima ', ' Python']

print(mystr.split('and', 2))
# 结果:['hello world ', ' itcast ', ' itheima and Python']

print(mystr.split(' '))
# 结果:['hello', 'world', 'and', 'itcast', 'and', 'itheima', 'and', 'Python']

print(mystr.split(' ', 2))
# 结果:['hello', 'world', 'and itcast and itheima and Python']

注意:如果分割字符是原有字符串中的子串,分割后则丢失该子串。

(3) join函数

join():用一个字符或子串合并字符串,即是将多个字符串合并为一个新的字符串。

1
字符或子串.join(多字符串组成的序列)

注意:序列包括 列表、元组、集合等,但是序列中的元素必须是字符串

示例

1
2
3
4
5
6
7
8
list1 = ['chuan', 'zhi', 'bo', 'ke']
t1 = ('aa', 'b', 'cc', 'ddd')

print('_'.join(list1))
# 结果:chuan_zhi_bo_ke

print('...'.join(t1))
# 结果:aa...b...cc...ddd

(4) 其他常用函数

capitalize():将字符串第一个字符转换成大写。

1
字符串序列.capitalize()

注意:capitalize()函数转换后,只字符串串第一个字符大写,其他的字符全都小写。

title():将字符串每个单词首字母转换成大写。

lower():将字符串中大写转小写。

upper():将字符串中小写转大写。

lstrip():删除字符串左侧空白字符。

rstrip():删除字符串右侧空白字符。

strip():删除字符串两侧空白字符。

(5) ljust函数

ljust():返回一个原字符串左对齐,并使用指定字符(默认空格)填充至对应长度的新字符串。

1
字符串序列.ljust(长度, 填充字符)

rjust():返回一个原字符串右对齐,并使用指定字符(默认空格)填充至对应长度的新字符串,语法和ljust()相同。

center():返回一个原字符串居中对齐,并使用指定字符(默认空格)填充至对应长度的新字符串,语法和ljust()相同。

(六) 字符串判断操作

所谓判断即是判断真假,返回的结果是布尔型数据类型:True 或 False。

(1) startswith函数

startswith():检查字符串是否是以指定子串开头,是则返回True,否则返回False。如果设置开始和结束位置下标,则在指定范围内检查。

1
字符串序列.startswith(子串, 开始位置下标, 结束位置下标)

示例

1
2
3
4
5
6
7
8
mystr = "hello world and itcast and itheima and Python "


print(mystr.startswith('hello'))
# 结果:True

print(mystr.startswith('hello', 5, 20))
# 结果False

(2) endswith函数

endswith():检查字符串是否是以指定子串结尾,是则返回True,否则返回False。如果设置开始和结束位置下标,则在指定范围内检查。

语法与startwith()相同

(3) isalpha函数

isalpha():如果字符串中的所有字符都是字母,则返回True,否则返回False。此函数用于检查参数是否包含任何字母字符 。

1
字符串.isalpha()

示例

1
2
3
4
5
6
7
mystr1 = 'hello'
mystr2 = 'hello12345'
mystr3 = 'hello world'

print(mystr1.isalpha()) # 结果:True
print(mystr2.isalpha()) # 结果:False
print(mystr3.isalpha()) # 结果:False

注意:空格不算字母

(4) isdigit函数

isdigit():如果字符串只包含数字则返回True,否则返回False。

用法与isalpha()相同。

(5) isalnum函数

isalnum():如果字符串至少有一个字符并且所有字符都是字母或数字则返回True,否则返回False。常用于检测字符串是否由字母和数字组成。

1
字符串.isalnum()

示例

1
2
3
4
5
mystr1 = 'aaa12345'
mystr2 = '12345-'

print(mystr1.isalnum()) # 结果:True
print(mystr2.isalnum()) # 结果:False

(6) isspace函数

isspace():如果字符串中只包含空白(空格),则返回True,否则返回False。

3.2 列表[]list()

(一) 列表的应用常景

思考:有一个人的姓名(TOM)怎么书写存储程序?
答:变量。
思考:如果一个班级100位学生,每个人的姓名都要存储,应该如何书写程序?声明100个变量吗?
答:列表即可, 列表一次性可以存储多个数据。

(二) 列表的格式

语法:

1
[数据1, 数据2, 数据3, 数据4, ......]

列表可以一次性存储多个数据,且可以为不同数据类型

列表中的元素可以重复

列表里面的元素可以是列表

(三) 列表查找操作

(1) 下标查找法

示例

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']

print(name_list[0]) # Tom
print(name_list[1]) # Lily
print(name_list[2]) # Rose

(2) 函数查找法

  • index():返回指定数据所在位置的下标 。
1
列表序列.index(数据, 开始位置下标, 结束位置下标)

示例

1
2
name_list = ['Tom', 'Lily', 'Rose']
print(name_list.index('Lily', 0, 2)) # 1

注意:如果查找的数据不存在则报错

  • count():统计指定数据在当前列列表中出现的次数。

示例

1
2
name_list = ['Tom', 'Lily', 'Rose', 'Lily']
print(name_list.count('Lily')) # 2
  • len():访问列表长度,即列表中数据的个数。

示例

1
2
name_list = ['Tom', 'Lily', 'Rose']
print(len(name_list)) # 3
(四) 列表判断操作
  • in:判断指定数据在某个列表序列,如果在返回True,否则返回False。
1
2
3
4
name_list = ['Tom', 'Lily', 'Rose']

print('Lily' in name_list) # 结果:True
print('Lilys' in name_list) # 结果:False
  • not in:判断指定数据不在某个列表序列,如果不在返回True,否则返回False。

in、not in是公共操作,字符串、列表、字典、元组等都有相应的用法。

(五) 列表增加操作

(1) append函数

append():列表结尾追加数据。

1
列表序列.append(数据)

示例1

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
name_list.append('xiaoming')

print(name_list)
# 结果:['Tom', 'Lily', 'Rose', 'xiaoming']

列表追加数据的时候,直接在原列表里面追加了指定数据,即修改了原列表,故列表为可变类型数据。

如果append()追加的数据是一个序列,则追加整个序列到列表

示例2

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
name_list.append(['xiaoming', 'xiaohong'])

print(name_list)
# 结果:['Tom', 'Lily', 'Rose', ['xiaoming', 'xiaohong']]

(2) extend函数

extend():列表结尾追加数据,如果数据是一个序列,则将这个序列的数据逐一添加到列表。

1
列表序列.extend(数据)

示例1

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
name_list.extend('xiaoming')

print(name_list)
# 结果:['Tom', 'Lily', 'Rose', 'x', 'i', 'a', 'o', 'm', 'i', 'n', 'g']

示例2

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
name_list.extend(['xiaoming', 'xiaohong'])

print(name_list)
# 结果:['Tom', 'Lily', 'Rose', 'xiaoming', 'xiaohong']

(3) insert函数

insert():指定位置新增数据。

1
列表序列.insert(位置下标, 数据)

示例

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
name_list.insert(1, 'xiaoming')

print(name_list)
# 结果:['Tom', 'xiaoming', 'Lily', 'Rose']
(六) 列表删除操作

(1) del函数

1
del 目标

示例1

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
del name_list

print(name_list)
# 结果:报错提示:name 'name_list' is not defined

示例2

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
del name_list[0]

print(name_list)
# 结果:['Lily', 'Rose']

(2) pop函数

pop():删除指定下标的数据(默认为最后一个),并返回该数据。

1
列表序列.pop(下标)

示例

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
del_name = name_list.pop(1)

print(del_name) # 结果:Lily
print(name_list) # 结果:['Tom', 'Rose']

(3) remove函数

remove():移除列表中某个数据的第一个匹配项。

1
列表序列.remove(数据)

示例

1
2
3
4
name_list = ['Tom', 'Rose', 'Lily', 'Rose']
name_list.remove('Rose')

print(name_list) # 结果:['Tom', 'Lily', 'Rose']

注意:只删除第一个匹配项。

(4) clear函数

clear():清空列列表。

1
2
3
4
name_list = ['Tom', 'Lily', 'Rose']
name_list.clear()

print(name_list) # 结果: []
(七) 列表修改操作

(1) 下标修改法

示例

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
name_list[0] = 'aaa'

print(name_list)
# 结果:['aaa', 'Lily', 'Rose']

(2) 函数修改法

  • reverse():将列表元素逆序排列

语法

1
列表.reverse()

示例

1
2
3
4
5
num_list = [1, 5, 2, 3, 6, 8]
num_list.reverse()

print(num_list)
# 结果:[8, 6, 3, 2, 5, 1]
  • sort():将列表元素递增或递减排序

语法

1
列表.sort(key=None, reverse=False)

参数:

  • key接受的是一个只有一个形参的函数key接收的函数返回值或者字典的键,表示此元素的权值,sort将按照权值大小进行排序 ,参考示例2。
  • reverse表示排序规则,reverse = True降序, reverse = False升序(默认)

示例1

1
2
3
4
5
num_list = [1, 5, 2, 3, 6, 8]
num_list.sort()

print(num_list)
# 结果:[1, 2, 3, 5, 6, 8],默认升序

示例2

1
2
3
4
5
6
7
8
9
10
11
12
# 获取列表的第二个元素
def takeSecond(elem):
return elem[1]

# 列表
random = [(2, 2), (3, 4), (4, 1), (1, 3)]

# 指定第二个元素排序
random.sort(key=takeSecond)
# 输出类别
print ('排序列表:', random)
# 结果:排序列表:[(4, 1), (2, 2), (1, 3), (3, 4)]
(八) 列表复制操作

copy():将列表复制一次

示例

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
name_li2 = name_list.copy()

print(name_li2)
# 结果:['Tom', 'Lily', 'Rose']
(九) 列表遍历操作

(1) while循环法

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']
i = 0
while i < len(name_list):
print(name_list[i])
i += 1

(2) for循环法

1
2
3
4
name_list = ['Tom', 'Lily', 'Rose']

for i in name_list:
print(i)
(十) 列表嵌套操作

所谓列表嵌套指的就是一个列表里面包含了其他的子列表。
应用场景:要存储班级一、二、三个班级学生姓名,且每个班级的学生姓名在一个列表。

1
name_list = [['小明', '小红', '小绿'], ['Tom', 'Lily', 'Rose'], ['张三', '李四', '王五']]

如何查找到数据”李四”?

1
2
3
4
# 第一步:按下标查找到李四所在的列表
print(name_list[2])
# 第⼆步:从李四所在的列表里面,再按下标找到数据李四
print(name_list[2][1])

3.3 元组()

(一) 元组的应用场景

思考:如果想要存储多个数据,但是这些数据是不能修改的数据,怎么做?
答:列表?列表可以一次性存储多个数据,但是列表中的数据允许更改。一个元组可以存储多个数据,元组内的数据是不能修改的

(二) 元组的格式

元组特点:定义元组使用小括号,且逗号隔开各个数据,数据可以是不同的数据类型。

示例1

1
2
3
4
# 多个数据元组
t1 = (10, 20, 30)
# 单个数据元组
t2 = (10,)

注意:如果定义的元组只有一个数据,那么这个数据后面要添加逗号,否则数据类型为唯一的这个数据的数据类型,如示例2所示

示例2

1
2
3
4
5
6
t2 = (10,)
print(type(t2)) # tuple
t3 = (20)
print(type(t3)) # int
t4 = ('hello')
print(type(t4)) # str
(三)元组常见操作——查找
**元组数据不支持修改(增加、删除等),只支持查找**
  • 按下标查找数据
1
2
tuple1 = ('aa', 'bb', 'ccc', 'bb', 12, True)
print(tuple1[0]) # aa
  • index():查找某个数据,如果数据存在返回对应的下标,否则报错,语法和列表、字符串的index方法相同。
1
2
tuple1 = ('aa', 'bb', 'ccc', 'bb', 12, True)
print(tuple1.index('aa')) # 0
  • count():统计某个数据在当前元组出现的次数。
1
2
tuple1 = ('aa', 'bb', 'ccc', 'bb', 12, True)
print(tuple1.count('bb')) # 2
  • len():统计元组中数据的个数。
1
2
tuple1 = ('aa', 'bb', 'ccc', 'bb', 12, True)
print(len(tuple1)) # 6
  • 特殊修改方法。。。

注意:元组内的直接数据如果修改则立即报错

1
2
3
tuple1 = ('aa', 'bb', 'cc', 'bb')
tuple1[0] = 'aaa'
# 报错

但是如果元组里面有列表,修改列表里面的数据则是支持的,故自觉很重要。

1
2
3
4
5
6
tuple2 = (10, 20, ['aa', 'bb', 'cc'], 50, 30)
print(tuple2[2]) # 访问到列列表

tuple2[2][0] = 'aaaaa'
print(tuple2)
# 结果:(10, 20, ['aaaaa', 'bb', 'cc'], 50, 30)

3.4 字典{}dict()

(一) 字典简介

字典类似与matlab的结构体

字典里面的数据是以键值对形式出现,字典数据和数据顺序没有关系,即字典不支持下标,后期无论数据如何变化,只需要按照对应的键的名字查找数据即可。

(二) 创建字典的语法
  • 符号为大括号
  • 数据为键值对形式出现
  • 各个键值对之间用逗号隔开

示例:

1
2
3
4
5
# 有数据字典
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
# 空字典
dict2 = {}
dict3 = dict()

注意:一般称冒号前面的为键(key),简称k;冒号后面的为值(value),简称v。

(三) 字典修改/增添操作

语法:

1
字典序列[key] = 值

注意:如果key存在则修改这个key对应的值;如果key不存在则新增此键值对。

1
2
3
4
5
6
7
8
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}

dict1['name'] = 'Rose'
# 结果:{'name': 'Rose', 'age': 20, 'gender': '男'}
print(dict1)
dict1['id'] = 110
# {'name': 'Rose', 'age': 20, 'gender': '男', 'id': 110}
print(dict1)

注意:由例子可知字典为可变类型

(四) 字典删除操作

(1) del() / del

del() / del:删除字典或删除字典中指定键值对

1
2
3
4
5
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
del dict1['gender']

print(dict1)
# 结果:{'name': 'Tom', 'age': 20}

注意:如删除的键字典里没有则会报错

(2) clear()

clear():清空字典

1
2
3
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
dict1.clear()
print(dict1) # {}
(五) 字典查找操作

(1) 按key值查找

1
2
3
4
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}

print(dict1['name']) # Tom
print(dict1['id']) # 报错

(2) get函数

语法

1
字典序列.get(key, 默认值)

注意:如果当前查找的key不存在则返回第二个参数(默认值),如果省略第二个参数,则返回None。

示例

1
2
3
4
5
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}

print(dict1.get('name')) # Tom
print(dict1.get('id', 110)) # 110
print(dict1.get('id')) # None

(3) keys函数

keys()函数:查找字典中的所有键key,返回可迭代对象(可用循环遍历的对象)

示例

1
2
3
4
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}

print(dict1.keys())
# dict_keys(['name', 'age', 'gender'])

(4) values函数

value()函数:查找字典中所有键对应的值,返回可迭代对象(可用循环遍历的对象)

示例

1
2
3
4
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}

print(dict1.values())
# dict_values(['Tom', 20, '男'])

(5) items函数

items()函数:查找字典中所有的键及其对应的值,返回可迭代对象(可用循环遍历的对象)

示例

1
2
3
4
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}

print(dict1.items())
# dict_items([('name', 'Tom'), ('age', 20), ('gender','男')]), 形式是元组
(六) 字典遍历操作

(1) 遍历字典的key

1
2
3
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for key in dict1.keys():
print(key)

(2) 遍历字典的value

1
2
3
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for value in dict1.values():
print(value)

(3) 遍历字典的元素

1
2
3
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for item in dict1.items():
print(item)

(4) 遍历字典的键值对

1
2
3
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for key, value in dict1.items():
print(f'{key} = {value}')

3.5 集合{}set()

(一) 创建集合

创建集合使用{}set() , 但是如果要创建空集合只能使用set() ,因为{}用来创建空字典

1
2
3
4
5
6
7
8
s2 = {10, 30, 20, 10, 30, 40, 30, 50}
print(s2)
s3 = set('abcdefg')
print(s3)
s4 = set()
print(type(s4)) # set
s5 = {}
print(type(s5)) # dict

特点:

  • 集合可以去掉重复数据
  • 集合数据是无序的,故不支持下标
(二) 集合增加数据操作

(1) add函数

1
2
3
4
s1 = {10, 20}
s1.add(100)
s1.add(10)
print(s1) # {100, 10, 20}

因为集合有去重功能,所以,当向集合内追加的数据是当前集合已有数据的话,则不不进⾏行行任何操作。

(2) update函数

update():追加的数据是序列

1
2
3
4
5
6
s1 = {10, 20}
# s1.update(100) # 报错
s1.update([100, 200])
s1.update('abc')
print(s1)
# 结果 {a, 100, 200, 10, 'b', 'c', 20}

因为集合无顺序,所有结果的顺序无所谓

(三) 集合删除数据操作

(1) remove函数

remove():删除集合中的指定数据,如果数据不存在则报错。

语法

1
集合.remove(元素)

示例

1
2
3
4
5
6
s1 = {10, 20}
s1.remove(10)
print(s1)
# s1={20}
s1.remove(50) # 报错
print(s1)

(2) discard函数

discard():删除集合中的指定数据,如果数据不存在也不会报错。

语法

1
集合.discard(元素)

示例

1
2
3
4
5
s1 = {10, 20}
s1.discard(10)
print(s1)
s1.discard(10)
print(s1)

(3) pop函数

pop():随机删除集合中的某个数据,并返回这个数据

语法

1
集合.pop()

示例

1
2
3
4
s1 = {10, 20, 30, 40, 50}
del_num = s1.pop()
print(del_num)
print(s1)
(四) 集合查找数据操作
  • in:判断数据在集合序列列
  • not in:判断数据不不在集合序列列
1
2
3
4
5
6
s1 = {10, 20, 30, 40, 50}

print(10 in s1)
# True
print(10 not in s1)
# False

第四章 公共操作

Python中常见的数据结构可以统称为容器(container)。序列(如列表和元组)、映射(如字典)以及集合(set)是三类主要的容器。

4.1 运算符

运算符 描述 支持的数据(容器)类型
+ 合并 字符串、列表、元组
* 复制 字符串、列表、元组
in 元素是否存在 字符串、列表、元组、字典、集合
not in 元素是否不存在 字符串、列表、元组、字典、集合
(一) +合并

语法

1
支持的数据类型的变量 + 支持的数据类型的变量

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 字符串
str1 = 'aa'
str2 = 'bb'
str3 = str1 + str2
print(str3) # aabb
# 2. 列表
list1 = [1, 2]
list2 = [10, 20]
list3 = list1 + list2
print(list3) # [1, 2, 10, 20]
# 3. 元组
t1 = (1, 2)
t2 = (10, 20)
t3 = t1 + t2
print(t3) # (10, 20, 100, 200)
(二) *复制

语法

1
支持的数据类型的变量 * 要复制的次数num

示例

1
2
3
4
5
6
7
8
# 1. 字符串
print('-' * 10) # ----------
# 2. 列表
list1 = ['hello']
print(list1 * 4) # ['hello', 'hello', 'hello', 'hello']
# 3. 元组
t1 = ('world',)
print(t1 * 4) # ('world', 'world', 'world', 'world')
(三) innot in

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 字符串
print('a' in 'abcd') # True
print('a' not in 'abcd') # False
# 2. 列表
list1 = ['a', 'b', 'c', 'd']
print('a' in list1) # True
print('a' not in list1) # False
# 3. 元组
t1 = ('a', 'b', 'c', 'd')
print('aa' in t1) # False
print('aa' not in t1) # True
# 4. 字典
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print('name' in dict1) # True
print('Tom' in dict1.values()) # True

注意:对于字典数据类型直接使用in/not in只能判断键,不能用来判断键对应的值

4.2 公共方法

函数 描述 支持容器
len() 计算容器中元素个数 字符串、列表、元组、字典、集合
del 或 del() 删除 字符串、列表、字典
max() 返回容器中元素最大值 字符串、列表、元组、集合、字典
min() 返回容器中元素最小值 字符串、列表、元组、集合、字典
range(start,end, step) 生成从start到end的数字,步长为 step,供for循环使用
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序
(一) len()函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 字符串
str1 = 'abcdefg'
print(len(str1)) # 7
# 2. 列表
list1 = [10, 20, 30, 40]
print(len(list1)) # 4
# 3. 元组
t1 = (10, 20, 30, 40, 50)
print(len(t1)) # 5
# 4. 集合
s1 = {10, 20, 30}
print(len(s1)) # 3
# 5. 字典
dict1 = {'name': 'Rose', 'age': 18}
print(len(dict1)) # 2
(二) del()函数
1
2
3
4
5
6
7
8
# 1. 字符串
str1 = 'abcdefg'
del str1
print(str1)
# 2. 列表
list1 = [10, 20, 30, 40]
del(list1[0])
print(list1) # [20, 30, 40]
(三) max()、min()函数
1
2
3
4
5
6
7
8
9
# 1. 字符串串
str1 = 'abcdefg'
print(max(str1)) # g
# 2. 列列表
list1 = [10, 20, 30, 40]
print(max(list1)) # 40
# 3.字典
dict1 = {'1': 'Tom', '2': 20, '7': '男'}
print(max(dict1)) # 7 返回键的最大值
(四) range()函数

注意:range()⽣生成的序列不包含end数字其返回值是一个可迭代对象

语法

1
range(开始数字, 结束数字, 步幅)

示例1

1
2
3
4
5
6
# 1 3 5 7 9
for i in range(1, 10, 2):
print(i)
# 0 1 2 3 4 5 6 7 8 9
for i in range(10):
print(i)

示例2

1
2
print(range(1,10,2))
# 结果 range(1, 10, 2)

其返回值是一个可迭代对象

(五) enumerate()函数

enumerate():返回N个元组,每个元组形式为(索引值,对应的值)

语法

1
enumerate(可遍历对象, start=0)

注意:start参数用来设置遍历数据的下标的起始值,默认为0。

示例

1
2
3
4
5
6
7
8
9
10
11
list1 = ['a', 'b', 'c']
for i in enumerate(list1):
print(i)
# (0, 'a')
# (1, 'b')
# (2, 'c')
for index, char in enumerate(list1, start=1):
print(f'下标是{index}, 对应的字符是{char}')
# 下标是1, 对应的字符是a
# 下标是2, 对应的字符是b
# 下标是3, 对应的字符是c

4.3 容器类型转换

(一) tuple()函数

tuple():将某个序列转换成元组

示例

1
2
3
4
5
6
7
8
list1 = [10, 20, 30, 40, 50, 20]
s1 = {100, 200, 300, 400, 500}

print(tuple(list1))
# (10, 20, 30, 40, 50, 20)

print(tuple(s1))
# (100, 200, 300, 400, 500)
(二) list()函数

list():将某个序列转换成列表

(三) set()函数

set():将某个序列转换成集合

注意:

  1. 集合可以快速完成列表去重
  2. 集合不支持下标

4.4 推导式

Python中只有列表、字典、集合有推导式,字符串和元组没有。

(一) 列表推导式

作用:用一个表达式创建一个有规律的列表或控制一个有规律列表。列表推导式又叫列表生成式。

示例1:传统方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 创建一个0-10的列表
# ========while方法实现==========
# 1. 准备⼀一个空列列表
list1 = []
# 2. 书写循环,依次追加数字到空列列表list1中
i = 0
while i < 10:
list1.append(i)
i += 1
print(list1)
# ========for方法实现==========
list1 = []
for i in range(10):
list1.append(i)
print(list1)

示例2:列表推导式

1
2
list1 = [i for i in range(10)]
print(list1)
  • 带if的列表推导式
1
2
3
4
5
6
7
# 创建0-10的偶数列表
# 方法一:range()步长实现
list1 = [i for i in range(0, 10, 2)]
print(list1)
# 方法二:if实现
list2 = [i for i in range(10) if i % 2 == 0]
print(list2)
  • 多个for循环实现列表推导式
1
2
3
4
# 需求:创建列表如下:
# [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
list1 = [(i, j) for i in range(1, 3) for j in range(3)]
print(list1)
(二) 字典推导式

思考:如果有如下两个列表:

1
2
list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']

如何快速合并为一个字典?

答:字典推导式;字典推导式作用:快速合并列表为字典或提取字典中目标数据。

示例1:创建一个字典:字典key是1-5数字,value是这个数字的2次方

1
2
dict1 = {i: i**2 for i in range(1, 5)}
print(dict1) # {1: 1, 2: 4, 3: 9, 4: 16}

示例2:将两个列表合并为一个字典

1
2
3
4
list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']
dict1 = {list1[i]: list2[i] for i in range(len(list1))}
print(dict1)

示例3:提取字典中目标数据

1
2
3
4
counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99}
# 需求:提取上述电脑数量量大于等于200的字典数据
count1 = {key: value for key, value in counts.items() if value >= 200}
print(count1) # {'MBP': 268, 'DELL': 201}
(三) 集合推导式
1
2
3
4
# 需求:创建一个集合,数据为下方列表的2次方
list1 = [1, 1, 2]
set1 = {i ** 2 for i in list1}
print(set1) # {1, 4}

第五章 函数

5.1 函数的作用

函数就是将一段具有独立功能的代码块整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求。
函数在开发过程中,可以更高效的实现代码重用

5.2 函数的使用步骤

(一) 定义函数
1
2
3
4
5
def 函数名(参数):
代码1
代码2
...
(return ...)
(二) 调用函数
1
函数名(参数)

注意:

  1. 不同的需求,参数可有可无;
  2. 在Python中,函数必须先定义后使用。
(三) 函数的说明文档

思考:定义一个函数后,程序员如何书写程序能够快速提示这个函数的作用?
答:注释

思考:如果代码多,我们是不是需要在很多代码中找到这个函数定义的位置才能看到注释?如果想更方便的查看函数的作用怎么办?
答:函数的说明文档

  • 定义函数的说明文档
1
2
3
4
def 函数名(参数):
""" 说明文档的位置 """
代码
......
  • 查看函数的说明文档
1
help(函数名)
(四) 函数嵌套调用

所谓函数嵌套调用指的是一个函数里面又调用了另外一个函数。

(五) 函数使用步骤小结
  • 函数的参数:函数调用的时候可以传入真实数据,增大函数的使用的灵活性
    • 形参:函数定义时书写的参数(非真实数据)
    • 实参:函数调用时书写的参数(真实数据)

5.3 函数的详细理解

(一) 变量作用域

变量量作用域指的是变量生效的范围,主要分为两类:局部变量和全局变量。

(1) 局部变量

所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效。

局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量。

(2) 全局变量
所谓全局变量,指的是在函数体内、外都能生效的变量。

思考:如果有一个数据,在函数A和函数B中都要使用,该怎么办?
答:将这个数据存储在一个全局变量里面。

(二) 函数的返回值

如果一个函数要有多个返回值,该如何书写代码?

1
2
3
4
def return_num():
return 1, 2
result = return_num()
print(result) # (1, 2)

注意:

  1. return后面可以连接列表、元组或字典,以返回多个值。
(三) 函数的参数

(1) 位置参数

位置参数:调用函数时根据函数定义的参数位置来传递参数。

示例

1
2
3
4
5
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')


user_info('TOM', 20, '男')

注意:传递和定义参数的顺序及个数必须一致

(2) 关键字参数

函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。

示例

1
2
3
4
5
6
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')


user_info('Rose', age=20, gender='女')
user_info('小明', gender='男', age=16)

注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序

(3) 缺省参数

缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值

(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)。

示例

1
2
3
4
5
6
7
8
def user_info(name, age, gender='男'):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')


user_info('TOM', 20)
# 您的名字是TOM, 年龄是20, 性别是男
user_info('Rose', 18, '女')
# 您的名字是Rose, 年龄是18, 性别是女

(4) 不定长参数

不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。

  • 包裹位置传递
1
2
3
4
5
6
7
8
9
def user_info(*args):
print(args)


user_info('TOM')
# ('TOM',)

user_info('TOM', 18)
# ('TOM', 18)

注意:传进函数的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。

  • 包裹关键字传递
1
2
3
4
5
6
7
def user_info(**kwargs):
print(kwargs)



user_info(name='TOM', age=18, id=110)
# {'name': 'TOM', 'age': 18, 'id': 110}

综上:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程。

(四) 拆包和交换变量值

(1) 拆包

  • 拆包:元组
1
2
3
4
5
6
7
def return_num():
return 100, 200


num1, num2 = return_num()
print(num1) # 100
print(num2) # 200
  • 拆包:字典
1
2
3
4
5
6
7
dict1 = {'name': 'TOM', 'age': 18}
a, b = dict1
# 对字典进行拆包,取出来的是字典的key
print(a) # name
print(b) # age
print(dict1[a]) # TOM
print(dict1[b]) # 18

(2) 交换变量值

需求:有变量a = 10 和b = 20 ,交换两个变量的值。

  • 方法1:借助第三变量存储数据。
1
2
3
4
5
6
7
8
9
10
# 1. 定义中间变量量
c = 0
# 2. 将a的数据存储到c
c = a
# 3. 将b的数据20赋值到a,此时a = 20
a = b
# 4. 将之前c的数据10赋值到b,此时b = 10
b = c
print(a) # 20
print(b) # 10
  • 方法2
1
2
3
4
a, b = 1, 2
a, b = b, a
print(a) # 2
print(b) # 1
(五) 引用

(1) 了解引用

在python中,值是靠引用来传递来的。
我们可以用id()来判断两个变量是否为同一个值的引用。 我们可以将id值理解为那块内存的地址标识

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. int类型
a = 1
b = a
print(b) # 1
print(id(a)) # 140708464157520
print(id(b)) # 140708464157520
a = 2
print(b) # 1,说明int类型为不可变类型
print(id(a)) # 140708464157552,此时得到是的数据2的内存地址
print(id(b)) # 140708464157520

# 2. 列表
aa = [10, 20]
bb = aa
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
aa.append(30)
print(bb) # [10, 20, 30], 列列表为可变类型
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432

(2) 引用当做实参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def test1(a):
print(a)
print(id(a))
a += a
print(a)
print(id(a))


# int:计算前后id值不不同
b = 100
test1(b)
# 列表:计算前后id值相同
c = [11, 22]
test1(c)
(六) 可变与不可变类型

所谓可变类型与不可变类型是指:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变。

  • 可变类型

    列表
    字典
    集合

  • 不可变类型

    整型
    浮点型
    字符串
    元组

不可变数据类型: 当该数据类型的对应变量的值发生了改变,那么它对应的内存地址也会发生改变,对于这种数据类型,就称不可变数据类型。

可变数据类型:当该数据类型的对应变量的值发生了改变,那么它对应的内存地址不发生改变,对于这种数据类型,就称可变数据类型。

总结:不可变数据类型更改后地址发生改变,可变数据类型更改地址不发生改变

5.4 递归函数

递归是一种编程思想

  • 函数内部自己调用自己
  • 递归函数必须有出口

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 需求:3以内数字累加和 3+2+1
def sum_numbers(num):
# 1.如果是1,直接返回1 -- 出口
if num == 1:
return 1
# 2.如果不不是1,重复执行累加:
result = num + sum_numbers(num-1)
# 3.返回累加结果
return result


sum_result = sum_numbers(3)
print(sum_result)
# 输出结果为6

5.5 lambda表达式/匿名函数

如果一个函数有一个返回值,并且只有一句代码,可以使用 lambda简化。

(一) lambda的语法
1
lambda 参数列表 : 表达式
  • lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用
  • lambda函数能接收任何数量的参数但只能返回一个表达式的值
  • 该表达式必须有返回值,表达式处可以视为:return 表达式

示例

1
2
3
4
5
6
7
8
9
10
# 计算a + b
# 方法1:普通函数实现=======================
def add(a, b):
return a + b


result = add(1, 2)
print(result)
# 方法2:lambda表达式=======================
print((lambda a, b: a + b)(1, 2))
(二) lambda的参数形式

(1) 无参数

1
print((lambda : 100)())

(2) 一个参数

1
print((lambda a: a)('hello world'))

(3) 默认参数

1
print((lambda a, b, c=100: a + b + c)(10, 20))

(4) 可变位置参数:*args

1
print((lambda *args: args)(10, 20, 30))

注意:这里的可变参数传入到lambda之后,返回值为元组。

(5) 可变关键字参数:*kwargs

1
print((lambda **kwargs: kwargs)(name='python', age=20))
(三) lambda表达式的应用

(1) 带判断的lambda

1
print((lambda a, b: a if a > b else b)(1000, 500))

(2) 列表数据按字典key的值排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
students = [
{'name': 'TOM', 'age': 20},
{'name': 'ROSE', 'age': 19},
{'name': 'Jack', 'age': 22}
]

# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)
# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)
# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)

5.6 高阶函数

把函数作为另一个函数的参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。

(一) 体验高阶函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 完成计算任意两个数字的绝对值之和
# 方法1:普通函数法====================
def add_num(a, b):
return abs(a) + abs(b)


result = add_num(-1, 2)
print(result) # 3

# 方法2:高阶函数法====================
def sum_num(a, b, f):
return f(a) + f(b)


result = sum_num(-1, 2, abs)
print(result) # 3

两种方法对比之后,发现方法2的代码会更加简洁。

函数式编程大量使用函数,减少了代码的重复,提高了灵活性,因此程序比较短,开发速度较快。

(二) 内置高阶函数

(1) map()函数

map(func, lst),将传入的函数变量func作用到lst列表变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(可迭代对象,Python3)返回。

语法

1
map(function, iterable, ...)

示例1

1
2
3
4
5
6
7
8
9
# :计算list1序列中各个数字的2次方
def func(x):
return x ** 2


list1 = [1, 2, 3, 4, 5]
result = map(func, list1)
print(result) # <map object at 0x0000013769653198>
print(list(result)) # [1, 4, 9, 16, 25]

示例2

1
2
list(map(lambda x: x ** 2, [1, 2, 3, 4, 5]))   # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]

(2) reduce()函数

reduce(func(x,y),lst),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算。

示例

1
2
3
4
5
6
7
8
9
# 计算list1序列中各个数字的累加和
import functools

def func(a, b):
return a + b

list1 = [1, 2, 3, 4, 5]
result = functools.reduce(func, list1)
print(result) # 15

reduce()在python3中不属于内置函数,需要从functools模块调用

(3) filter()函数

filter(func, lst)函数用于过滤序列,过滤掉不符合条件的元素,返回一个filter对象。如果要转换为列表,可以使用list()来转换。和map()类似,filter()也接收一个函数和一个序列。和map()不同的时,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

示例

1
2
3
4
5
6
7
8
def func(x):
return x % 2 == 0 #返回True或False


list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result = filter(func, list1)
print(result) # <filter object at 0x0000017AF9DC3198>
print(list(result)) # [2, 4, 6, 8, 10]

第六章 文件操作

6.1 文件操作的作用

思考:文件操作包含什么?
答:打开、关闭、读、写、复制….

思考:文件操作的的作用是什么?
答:读取内容、写入内容、备份内容……

文件操作的作用就是把一些内容(数据)存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力。

6.2 文件的基本操作

(一) 打开/创建文件——open()

在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下:

1
open(name, mode)

name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。
mode:设置打开文件的模式(访问模式):只读、写入、追加等。

(1) 打开文件模式

模式 描述
r 以只读方式打开文件。文件的指针将会放在文件的开头,这是默认模式
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开⽂文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
w+ 打开一个文件用于读写。如果该文件已存在则打开⽂文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开⽂文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

注意:对于a的模式打开文件,由于文件指针在文件的结尾处,因此无法使用read()读出内容,但是可以使用seek()函数改变文件指针

注意:使用w模式打开文件,一旦文件打开就自动删除文件的内容

示例

1
f = open('test,txt', 'w)
(二) 文件对象方法

(1) 写方法

1
文件对象.write('内容')

示例

1
2
3
4
5
6
# 1. 打开文件
f = open('test.txt', 'w')
# 2.文件写入
f.write('hello world')
# 3. 关闭文件
f.close()

注意:

  1. w 和a 模式:如果文件不存在则创建该文件;如果文件存在, w 模式先清空再写入, a 模式直接末尾追加。
  2. r 模式:如果文件不存在则报错。

(2) 读方法

① read()函数

1
文件对象.read(num)

num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。

② readline()函数

readline()一次读取一行内容。

1
2
3
4
5
6
7
f = open('test.txt')
content = f.readline()
print(f'第一行:{content}')
content = f.readline()
print(f'第二行:{content}')
# 关闭文件
f.close()

③ readlines()函数

readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。

1
2
3
4
5
6
f = open('test.txt')
content = f.readlines()

print(content) # ['hello world\n', 'abcdefg\n', 'aaa\n', 'bbb\n', 'ccc']
# 关闭文件
f.close()

(3) 文件指针方法

1
文件对象.seek(偏移量, 起始位置)

偏移量:n,单位字节

起始位置:
0:文件开头,1:当前位置,2:文件结尾

(4) 关闭文件

1
文件对象.close()
(三) 文件备份

6.3 文件和文件夹的操作

在Python中文件和文件夹的操作要借助os模块里面的相关功能,具体步骤如下:

1
2
3
4
# 1. 导入os模块
import os
# 2. 使用os模块相关功能
os.函数名()
(一) 文件重命名
1
os.rename(目标文件名, 新文件名)
(二) 删除文件
1
os.remove(目标文件名)
(三) 创建文件夹
1
os.mkdir(文件夹名字)
(四) 删除文件夹
1
os.rmdir(文件夹名字)
(五) 获取当前目录
1
os.getcwd()
(六) 改变默认目录

os.chdir()方法用于改变当前工作目录到指定的路径。

1
os.chdir(目录)
(七) 获取目录列表
1
os.listdir(目录)

6.4 文件路径操作

(一) Windows下的路径写法

由于windows的路径分隔符使用的是反斜杠\,它刚刚好是转义字符,故可能发生冲突

1
2
3
4
5
6
7
8
9
10
# 错误示范:反斜杠似乎被解释为转义字符而不是分隔字符
path = "F:\Python\test.txt"
path = "F:\\Python\test.txt"

"""以下三种方式都是可行的"""
path = "F:\Python\\test.txt"
path = "F:\\Python\\test.txt"
path = "F:\Python\\test.txt"
'''绝对路径的最后一个反斜杠使用了双反斜杠时就正常'''
'''原因是最后一个反斜杠可以与它紧挨着的字符t构成转义效果'''

结论:使用绝对路径的时候,要注意在绝对路径中使用的反斜杠与它后面紧跟着的字符会不会构成转义效果,如果会产生转义效果,如\t \n \r等等,则必须使用双反斜杠来取消单反斜杠的转义效果。如果产生了转义字符带来的错误,会出现open()提示 “Invalid arguments”

**Python中windows路径的3种写法**
1
"C:\\Users\\10799\\Desktop\\learn\\C\\homework\\5"
1
r"C:\Users\10799\Desktop\learn\C\homework\5"
1
"C:/Users/10799/Desktop/learn/C/homework/5"

但是不可以这样写:

1
"C:\Users\10799\Desktop\learn\C\homework\5"
(二) 绝对路径与相对路径

相对路径相关写法:

../ 表示当前文件所在的目录的上一级目录
./表示当前文件所在的目录(可以省略)
/表示当前站点的根目录(域名映射的硬盘目录)

第七章 面向对象基础

7.1 理解面向对象

面向对象就是将编程当成是一个事物,对外界来说,事物是直接使用的,不用去管他内部的情况。而编程就是设置事物能够做什么事。

面向对象是一种抽象化的编程思想,很多编程语言中都有的一种思想。
例如:洗衣服
思考:几种途径可以完成洗衣服?
答: 手洗 和 机洗。
手洗:找盆 - 放水 - 加洗衣粉 - 浸泡 - 搓洗 - 拧干水 - 倒水 - 漂洗N次 - 拧干 - 晾晒。
机洗:打开洗衣机 - 放衣服 - 加洗衣粉 - 按下开始按钮 - 晾晒。
思考:对比两种洗衣服途径,同学们发现了了什么?
答:机洗更简单
思考:机洗,只需要找到一台洗衣机,加入简单操作就可以完成洗衣服的工作,而不需要关心洗衣机内部发⽣生了了什么事情。

  • 面向对象的三大特征
    • 封装
      • 将属性和方法书写到类的里面的操作即为封装
      • 封装可以为属性和⽅方法添加私有权限
    • 继承
      • 子类默认继承父类的所有属性和方法
      • 子类可以重写父类属性和方法
    • 多态
      • 传入不同的对象,产生不同的结果

7.2 类和对象

类和对象的关系:用类去实例化/创建一个对象

(一) 理解类和对象

(1) 类

类是对一系列具有相同特征和行为的事物的统称,是一个抽象的概念,不是真实存在的事物。

  • 特征即是属性——变量
  • 行为即是方法——函数

类比如是制造洗衣机时要用到的图纸,也就是说类是用来创建对象。

(2) 对象

对象是类创建出来的真实存在的事物,例如:洗衣机。也就是说开发中先有类,再有对象。

(二) 面向对象实现方法

(1) 定义类

语法

1
2
3
class 类名():
代码
......

注意:类名要满足标识符命名规则,同时遵循大驼峰命名习惯。e.g. 每个单词的首字母都采用大写字母,例如:FirstName

(2) 创建对象

对象又名实例。语法如下

1
对象名 = 类名()

示例

1
2
3
4
5
6
# 创建对象
haier1 = Washer()
# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)
# haier对象调用实例方法
haier1.wash()

(3) self

self指的是调用该函数的对象。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 定义类
class Washer():
def wash(self):
print('我会洗衣服')
print(self) # <__main__.Washer object at 0x0000024BA2B34240>


# 2. 创建对象
haier1 = Washer()
print(haier1) # <__main__.Washer object at 0x0000018B7B224240>
# haier1对象调用实例方法
haier1.wash()
haier2 = Washer()
print(haier2) # <__main__.Washer object at 0x0000022005857EF0>

注意:打印对象和self得到的结果是一致的,都是当前对象的内存中存储地址。

7.3 添加和获取对象属性

属性即是特征,比如:洗衣机的宽度、高度、重量…
对象属性既可以在类外面添加和获取,也能在类里面添加和获取。

(一) 类外面添加对象属性

语法

1
对象名.属性名 = 值

示例

1
2
haier1.width = 500
haier1.height = 800
(二) 类外面获取对象属性

语法

1
对象名.属性名

示例

1
2
print(f'haier1洗衣机的宽度是{haier1.width}')
print(f'haier1洗衣机的高度是{haier1.height}')
(三) 类里面获取对象属性

语法

1
self.属性名

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 定义类
class Washer():
def print_info(self):
# 类里面获取实例属性
print(f'haier1洗衣机的宽度是{self.width}')
print(f'haier1洗衣机的高度是{self.height}')


# 创建对象
haier1 = Washer()
# 添加实例例属性
haier1.width = 500
haier1.height = 800
haier1.print_info()

7.4 魔法方法

在Python中,__xx__()的函数叫做魔法方法,指的是具有特殊功能的函数。

魔法方法是python内置方法,不需要主动调用,存在的目的是为了给python的解释器进行调用,几乎每个魔法方法都有一个对应的内置函数,或者运算符,当我们对这个对象使用这些函数或者运算符时就会调用类中的对应魔法方法,可以理解为重写这些python的内置函数(类似于方法重载)。

(一) __init__()魔法方法

思考:洗衣机的宽度高度是与生俱来的属性,可不可以在生产过程中就赋予这些属性呢?
答:理应如此。

(1) __init__() 方法

__init__() 方法的作用:初始化对象。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Washer():
# 定义初始化功能的函数
def __init__(self):
# 添加实例属性
self.width = 500
self.height = 800
pass

def print_info(self):
# 类里面调用实例属性
print(f'洗衣机的宽度是{self.width}, 高度是{self.height}')
pass

haier1 = Washer()
haier1.print_info()

注意:
__init__() 方法,在创建一个对象时默认被调用,不需要手动调用;

__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去;

__init__() 方法不需要调用是指在在创建对象时会自动调用,但是如果在没有创建对象时,需要调用

(2) 带参数的__init__()

思考:一个类可以创建多个对象,如何对不同的对象设置不同的初始化属性呢?
答:传参数。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height
def print_info(self):
print(f'洗衣机的宽度是{self.width}')
print(f'洗衣机的高度是{self.height}')


haier1 = Washer(10, 20)
haier1.print_info()
haier2 = Washer(30, 40)
haier2.print_info()
(二) __str__()魔法方法

当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了了__str__()方法,那么就会打印从
在这个方法中 return 的数据。

示例

1
2
3
4
5
6
7
8
9
10
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height
def __str__(self):
return '这是海尔洗衣机的说明书'


haier1 = Washer(10, 20)
print(haier1) # 这是海尔洗衣机的说明书
(三) __del__()魔法方法

当删除对象时,python解释器也会默认调用__del__() 方法。(即使没有删除语句,在程序结束时也会调用该函数)

示例

1
2
3
4
5
6
7
8
9
10
11
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height

def __del__(self):
print(f'{self}对象已经被删除')


haier1 = Washer(10, 20)
del haier1 # <__main__.Washer object at 0x0000026118223278>对象已经被删除
(四) __call__()魔法方法

__call__()方法的作用其实是把一个类的实例化对象变成了可调用对象,只要类里实现了__call__()方法就行。

如当类里没有实现__call__()时,此时的对象p只是个类的实例,不是一个可调用的对象,当调用它时会报错:’Person’ object is not callable

1
2
3
4
5
6
7
8
9
10
class Person(object)
def __init__(self, name)
self.name = name
pass
pass

Wjh = Person('WJH')
# 未写方法__call__时强行调用对象
Wjh('Bob')
# 报错:'Person' object is not callable
1
2
3
4
5
6
7
8
9
10
11
12
class Person(object)
def __init__(self, name)
self.name = name
pass
def __call__(self, friend)
print(f'我的名字是{self.name},我的朋友叫{friend}')
pass
pass

Wjh = Person('WJH')
Wjh('Bob')
# 我的名字是WJH,我的朋友叫Bob

第八章 面向对象—继承

8.1 继承的概念

生活中的继承,一般指的是子女继承父辈的财产。

Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法,具体如
下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 父类A
class A(object):
def __init__(self):
self.num = 1
def info_print(self):
print(self.num)


# 子类B
class B(A):
pass


result = B()
result.info_print() # 1

在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。

  • **子类不重写`__init__`,实例化子类时,会自动调用父类定义的`__init__`。**
  • 如果子类重写了__init__ 方法,那么父类的属性是不能直接调用的。

8.2 单继承

一个子类只有一个直接父类时称这个继承关系为单继承。

故事主线:一个煎饼果子老师傅,在煎饼果子界摸爬滚打多年,研发了一套精湛的摊煎饼果子的技术。师⽗父要把这套技术传授给他的唯一的最得意的徒弟。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 师⽗父类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

# 2. 徒弟类
class Prentice(Master):
pass

# 3. 创建对象daqiu
daqiu = Prentice()
# 4. 对象访问实例例属性
print(daqiu.kongfu)

8.3 多继承

一个子类有两个或以上直接父类时称这个继承关系为多继承。

故事推进:daqiu是个爱学习的好孩子,想学习更多的煎饼果子技术,于是,在百度搜索到黑马程序员,报班学习煎饼果子技术。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

# 创建学校类
class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

class Prentice(School, Master):
pass

daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()

注意:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。

8.4 子类重写父类同名方法和属性

子类和父类具有同名属性和方时,默认使用子类的同名属性和方法。

一个对象调用一个方法,如果本类中没有这个方法那就会按照mro顺序去找与他相关的类是否有这个方法,如果找到顶级类object依然没有这个方法,那就会报错。包括后面的super().方法()也是按照mro顺序去找的,至于mro是怎么定义的,大家可以搜索下【拓扑排序】

故事:daqiu掌握了师父和培训的技术后,自己潜心钻研出自己的独门配方的一套全新的煎饼果子技术。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

# 独创配方
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()

print(Prentice.__mro__) # 通过打印__mro__可以查看类的继承层级顺序

8.5 子类调用父类的同名方法和属性

故事:很多顾客都希望也能吃到古法和黑马的技术的煎饼果子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 若先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)

daqiu = Prentice()
daqiu.make_cake()
daqiu.make_master_cake()
daqiu.make_school_cake()
daqiu.make_cake()

8.6 多层继承

一个子类可以有一个父类,一个父类还可以有一个父类。

故事:N年后,daqiu老了,想要把所有技术传承给自己的徒弟。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 若先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)

# 徒孙类
class Tusun(Prentice):
pass

xiaoqiu = Tusun()
xiaoqiu.make_cake() # 运用[独创煎饼果子配方]制作煎饼果子
xiaoqiu.make_school_cake() # 运用[黑马煎饼果子配方]制作煎饼果子
xiaoqiu.make_master_cake() # 运用[古法煎饼果子配方]制作煎饼果子

8.7 super()调用父类方法

使用super()可以自动查找父类。调用顺序遵循 __mro__ 类属性的顺序。比较适合单继承使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')

class School(Master):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 方法2.1
# super(School, self).__init__()
# super(School, self).make_cake()
# 方法2.2
super().__init__()
super().make_cake()

class Prentice(School):
def __init__(self):
self.kongfu = '[独创煎饼果子技术]'
def make_cake(self):
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')

# 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)

# 一次性调用父类的同名属性和方法
def make_old_cake(self):
# 方法一:代码冗余;父类名如果变化,这里代码需要频繁修改
# Master.__init__(self)
# Master.make_cake(self)
# School.__init__(self)
# School.make_cake(self)
# 方法二: super()
# 方法2.1 super(当前类名, self).函数()
# super(Prentice, self).__init__()
# super(Prentice, self).make_cake()
# 方法2.2 super().函数()
super().__init__()
super().make_cake()


daqiu = Prentice()
daqiu.make_old_cake()

注意: super() 在 python2、3中的区别

python3直接写成 super().方法名(参数)

python2必须写成 super(父类,self).方法名(参数)

8.8 私有权限

主要介绍了Python 私有属性与私有方法,私有属性是指在 Python 的面向对象开发过程中,对象的某些属性只想在对象的内部被使用,但不想在外部被访问到这些属。

参考笔记:Python 私有属性与私有方法https://www.jb51.net/article/239280.htm

(一) 定义私有属性和方法

(1) 私有属性/方法是什么?

**两个下划线开头的属性是私有的(private)。其他为公共的(public)**。
  • 私有属性:

是指在 Python 的面向对象开发过程中,对象的某些属性只想在对象的内部被使用,但不想在外部被访问到这些属性。即:私有属性是对象不愿意公开的属性。

  • 私有方法:

是指在 Python 的面向对象开发过程中,对象的某些方法或者称为函数只想在对象的内部被使用,但不想在外部被访问到这些方法或函数。即:私有方法是对象不愿意公开的方法或函数。

(2) 示例语法

1
2
3
4
5
6
7
class Staff:
    def __init__(self, s_name, s_salary):
      self.s_name = s_name
      self.__salary = s_salary
      
    def __secret(self):
      print("%s 的工资是 %d" % (self.s_name, self.__salary))
  • (1). __salary是以两个下划线开头来定义的私有属性。
  • (2). __secret(self)是以两个下划线开头来定义的私有方法。
(二) 私有属性的调用
  • 类内部可以访问私有属性(方法)
  • 类外部不能直接访问私有属性(方法)
  • 类外部可以通过”_类名__私有属性(方法)名”访问私有属性(方法)(私有属性和私有方法)

方法本质上也是属性!只不过是可以通过()执行而执行

(三) 获取和修改私有属性值

在Python中,一般定义公有方法函数名get_xx用来获取私有属性,定义set_xx用来修改私有属性值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Person(object): 
def __init__(self):
self.name = "小明"
self.__age = 20

#获取私有属性的值
def get_age(self):
return self.__age

#设置私有属性的值
def set_age(self, new_age):
self.__age = new_age


#定义一个对象
p = Person()
#强行获取私有属性
#崇尚一切靠自觉
print(p._Person__age)
print(p.name)
#想在类的外面获取对象的属性
ret = p.get_age()
print(ret)

#想在类的外面修改对象私有属性的值
p.set_age(30)
print(p.get_age())

第九章 面向对象—多态—其他知识

9.1 多态

(一) 了解多态

多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)。

  • 定义:

多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果。

  • 好处:

调用灵活,有了多态更容易写出通用的代码,做出通用的编程,以适应需求的不断变化!

  • 实现步骤:
    • 定义父类,并提供公共方法
    • 定义子类,并重写父类方法
    • 传递子类对象给调用者,可以看到不同子类执行效果不同
(二) 多态示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Dog(object):
def work(self): # 父类提供统一的方法,哪怕是空方法
print('指哪打哪...')


class ArmyDog(Dog): # 继承Dog类
def work(self): # 子类重写父类同名方法
print('追击敌人...')


class DrugDog(Dog):
def work(self):
print('追查毒品...')


class Person(object):
def work_with_dog(self, dog): # 传入不同的对象执行不同的代码,即不同的work函数
dog.work()


ad = ArmyDog()
dd = DrugDog()
daqiu = Person()
daqiu.work_with_dog(ad)
daqiu.work_with_dog(dd)

9.2 类属性和实例属性

(一) 类属性

(1) 设置和访问类属性

  • 类属性就是类对象所拥有的属性,它被该类的所有实例对象所共有。
  • 类属性可以使用类对象实例对象访问。

示例

1
2
3
4
5
6
7
8
class Dog(object):
tooth = 10

wangcai = Dog()
xiaohei = Dog()
print(Dog.tooth) # 10
print(wangcai.tooth) # 10
print(xiaohei.tooth) # 10

(2) 类属性的优点

  • 类的实例 记录的某项数据 始终保持一致时,则定义类属性。
  • 实例属性要求每个对象为其单独开辟一份内存空间来记录数据,而类属性为全类所共有,仅占用一份内存,更加节省内存空间。

(3) 修改类属性

类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了了一个实例属性。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Dog(object):
tooth = 10


wangcai = Dog()
xiaohei = Dog()
# 修改类属性
Dog.tooth = 12
print(Dog.tooth) # 12
print(wangcai.tooth) # 12
print(xiaohei.tooth) # 12

# 不能通过对象修改属性,如果这样操作,实则是创建了一个实例属性
wangcai.tooth = 20
print(Dog.tooth) # 12
print(wangcai.tooth) # 20
print(xiaohei.tooth) # 12
(二) 实例属性

示例

1
2
3
4
5
6
7
8
9
10
11
12
class Dog(object):
def __init__(self):
self.age = 5

def info_print(self):
print(self.age)


wangcai = Dog()
print(wangcai.age) # 5
# print(Dog.age) # 报错:实例属性不能通过类访问
wangcai.info_print() # 5

9.3 类方法和静态方法

(一) 类方法

(1) 类方法特点

  • 第一个形参是类对象的方法
  • 需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数。

(2) 类方法使用场景

  • 当方法中 需要使用类对象 (如访问私有类属性等)时,定义类方法
  • 类方法一般和类属性配合使用

示例

1
2
3
4
5
6
7
8
9
10
11
class Dog(object):
__tooth = 10 # 私有-类-属性

@classmethod
def get_tooth(cls):
return cls.__tooth


wangcai = Dog()
result = wangcai.get_tooth()
print(result) # 10

(二) 静态方法

(1) 静态方法特点

  • 需要通过装饰器@staticmethod来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)。
  • 静态方法也能够通过实例对象类对象去访问。

(2) 静态方法使用场景

  • 当方法中既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象(如类属性、类方法、创建实例等)时,定义静态方法
  • 取消不需要的参数传递,有利于减少不必要的内存占用和性能消耗

示例

1
2
3
4
5
6
7
8
9
10
class Dog(object):
@staticmethod
def info_print():
print('这是一个狗类,用于创建狗实例....')


wangcai = Dog()
# 静态方法既可以使用对象访问又可以使用类访问
wangcai.info_print()
Dog.info_print()

第十章 模块和包

10.1 模块

Python 模块(Module),是一个 Python文件,以 .py 结尾,包含了Python对象定义和Python语句句。模块能定义函数,类和变量,模块里也能包含可执行的代码。

(一) 导入模块
  • import 模块名
  • from 模块名 import 功能名
  • from 模块名 import *
  • import 模块名 as 别名
  • from 模块名 import 功能名 as 别名
(二) 制作模块

在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。也就是说自定义模块名必须要符合标识符命名规则。

(1) 定义模块

新建一个Python文件,命名为my_module1.py ,并定义testA函数。

1
2
def testA(a, b):
print(a + b)

(2) 测试模块

在实际开中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,这个开发人员会自行在py文件中添加一些测试信息,例如在my_module1.py文件中添加测试代码。

1
2
3
4
def testA(a, b):
print(a + b)

testA(1, 1)

此时,无论是当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自动执行testA函数的调用。解决办法如下:

1
2
3
4
5
6
def testA(a, b):
print(a + b)

# 只在当前文件中调用该函数,其他导入的文件内不符合该条件,则不执行testA函数调用
if __name__ == '__main__':
testA(1, 1)

注意:__name__是一个系统变量,当在自己文件内时其值为__main__,当在其他文件调用时其值为文件名

(3) 调用模块

1
2
import my_module1
my_module1.testA(1, 1)

(4) 注意事项

如果使用from .. import ..from .. import *导入多个模块的时候,且模块内有同名功能。当调用这个同名功能的时候,调用到的是后面导入的模块的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
# my_module1: 模块1代码
def my_test(a, b):
print(a + b)

# my_module2:模块2代码
def my_test(a, b):
print(a - b)

# 导入模块和调⽤用功能代码
from my_module1 import my_test
from my_module2 import my_test
# my_test函数是模块2中的函数
my_test(1, 1) # 0
(三) 模块定位顺序

当导入一个模块,Python解析器对模块位置的搜索顺序是:

  1. 当前目录
  2. 如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
  3. 如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
    注意:
  • 自己的文件名不要和已有模块名重复,否则导致模块功能无法使用
  • 使用from 模块名 import 功能时,若功能名字和自己定义的函数名重复,调用到的是最后定义或导入的功能。
  • 使用import 模块名时,则会导致名字覆盖
(四) __all__变量

如果一个模块文件中有__all__变量,当使用from xxx import *导入时,只能导入这个列表中的元素。

1
2
3
4
5
6
7
8
# my_module1模块代码
__all__ = ['testA']

def testA():
print('testA')

def testB():
print('testB')

导入模块

1
2
3
4
from my_module1 import *

testA() # 'testA'
testB() # __all__列表没有testB,调用报错

10.2 包

包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py文件,那么这个文件夹就称之为包。

(一) 制作包

[New] — [Python Package] — 输入包名 — [OK] — 新建功能模块(有联系的模块)。
注意:新建包后,包内部会自动创建__init__.py文件,这个文件控制着包的导入行为。

(1) 快速示例

  1. 新建包mypackage
  2. 新建包内模块: my_module1 和 my_module2
  3. 模块内代码如下
1
2
3
4
5
# my_module1
print(1)

def info_print1():
print('my_module1')
1
2
3
4
5
# my_module2
print(2)

def info_print2():
print('my_module2')
(二) 导入包

(1) 方法一

1
2
3
import 包名.模块名
# 调用方法
包名.模块名.目标函数

(2) 方法二

注意:必须在__init__.py文件中添加__all__ = [],控制允许导入的模块列表。

1
2
3
from 包名 import *
# 调用方法
模块名.目标

示例

1
2
from my_package import *
my_module1.info_print1()

第十一章 异常处理


  • Python的模块(module)、包(package)和库的区别
    • 模块(module)其实就是文件,里面定义了一些函数、类、变量等,可以作为module的文件类型有”.py”、”.pyo”、”.pyc”、”.pyd”、”.so”、”.dll” 等;
    • 包(package)是多个模块module的聚合体形成的文件夹,里面可以是多个py文件,也可以嵌套文件夹;
    • 库是参考其他编程语言的说法,是指完成一定功能的代码集合,在python中的形式就是模块和包;
  • 如何导入python包和模块
    • 模块的导入 就是直接import文件名即可 ;
    • 导入包不能随便使用其中的模块,要导入到具体模块或者变量的层次

第十二章 OS、SYS和argparse模块

12.1 OS模块

(一) OS模块定义

在自动化过程当中,经常需要查找操作文件,比如说查找配置文件(从而读取配置文件的信息),查找测试报告(从而发送测试报告邮件),经常要对大量文件和大量路径进行操作,这就依赖于os模块。

(二) OS模块常用方法
当前路径以及路径下的文件 解释
os.getcwd() 查看当前所在路径
os.pardir 获取当前目录的父目录(上一级目录),以字符串形式显示目录名
os.listdir(path) 列举目录下的所有文件。返回的是列表类型。
os.path.abspath(path) 返回path的绝对路径。
os.path.join(path1, path2) 将path进行组合,若其中有绝对路径,则之前的path将被删除。
os.path.exists(path) path:要判断的路径,可用绝对路径,也可用相对路径。
返回值:给定的路径存在则返回 True,否则返回 False。
os.path.dirname(path) 返回path中的文件夹部分,结果不包含\
os.path.basename(path) 返回path中的文件名
os.path.getsize() 文件或文件夹的大小

注意:

path参数不写,默认当前项目路径,若写,则既可使用绝对路径r"E:\A.毕业设计\前期基础知识学习\deep learning project\MINIST-master\data",又可使用相对路径r".\dataset"(当前项目路径下的子文件夹dataset)

os.path模块的更多函数参考:Python常用基础模块之os.path模块详解

12.2 SYS模块

(一) SYS模块定义

OS标准库是操作系统接口模块,提供了操作系统相关功能的调用函数。 Python的os模块是用于与操作系统进行交互的模块,它提供了许多函数和方法来执行文件和目录操作、进程管理、环境变量访问等

sys模块是与python解释器交互的一个接口。sys 模块提供了许多函数和变量来处理 Python 运行时环境的不同部分。 可以用于获取命令行参数、控制程序的执行、管理模块和包、处理异常等。

(二) SYS模块常用方法
  • 命令行参数

sys模块提供了一些函数和变量用于获取和处理命令行参数。

sys.argv:是一个包含命令行参数的列表,其中第一个元素是脚本的名称。可以使用sys.argv[1:]来获取除脚本名称外的所有参数。

1
2
3
4
5
6
7
8
9
10
11
sys.argv[0]		# 是脚本的名称。
sys.argv[1:] # 是除脚本名称外的所有参数。

# ==========例子=====================
import sys
# 获取脚本的名称
script_name = sys.argv[0]
print("脚本名称:", script_name)
# 获取除脚本名称外的所有参数
args = sys.argv[1:]
print("参数列表:", args)
  • 系统相关

sys模块还提供了一些函数和变量用于与系统相关的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sys.platform	# 是一个字符串,表示当前运行的操作系统平台。
sys.version # 是一个字符串,表示当前Python解释器的版本。
sys.exit([arg]) # 用于退出程序,可选地指定一个整数参数作为退出状态码。

# ==========例子=====================
import sys
# 获取当前操作系统平台
platform = sys.platform
print("操作系统平台:", platform)
# 获取当前Python解释器的版本
version = sys.version
print("Python版本:", version)
# 退出程序
sys.exit(0)
  • 模块和包

sys模块还提供了一些函数和变量用于管理模块和包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sys.modules		# 是一个字典,包含了当前已导入的所有模块。
sys.path # 是一个列表,包含了Python解释器在搜索模块时要查找的路径。
sys.meta_path # 是一个列表,包含了当前已注册的所有导入钩子

# ==========例子=====================
import sys
# 获取已导入的所有模块
modules = sys.modules
print("已导入的模块:", modules)
# 获取模块搜索路径
path = sys.path
print("模块搜索路径:", path)
# 获取已注册的导入钩子
meta_path = sys.meta_path
print("已注册的导入钩子:", meta_path)
  • 异常处理

sys模块还提供了一些函数和变量用于处理异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sys.exc_info()		# 返回当前异常的相关信息,包括异常类型、异常值和异常追踪信息。
sys.exc_clear() # 清除当前异常。
sys.exc_type # 是一个变量,保存了当前异常的类型。
sys.exc_value # 是一个变量,保存了当前异常的值。
sys.exc_traceback # 是一个变量,保存了当前异常的追踪信息。

# ==========例子=====================
import sys
try:
# 产生一个异常
raise ValueError("发生了一个错误")
except:
# 获取当前异常的相关信息
exc_type, exc_value, exc_traceback = sys.exc_info()
print("异常类型:", exc_type)
print("异常值:", exc_value)
print("异常追踪信息:", exc_traceback)
# 清除当前异常
sys.exc_clear()

12.3 argparse模块

argparse 是一个用来解析命令行参数和选项的 Python 库,它是 Python 标准库的一部分。

argparse 模块使编写用户友好的命令行界面变得容易

程序定义了所需的参数,而 argparse 将找出如何从 sys.argv</font> 中解析这些参数。

argparse 模块还会自动生成帮助和使用消息,并在用户为程序提供无效参数时发出错误。

简而言之,就是汇总函数接口,方便传参。

(一 ) argparse定义四个步骤
  • 导入argparse包 —— import argparse
  • 创建一个命令行解析器对象 —— 创建 ArgumentParser() 对象
  • 给解析器添加命令行参数 —— 调用 add_argument() 方法添加参数
  • 解析命令行的参数 —— 使用 parse_args() 解析添加的参数
(二) argparse的使用场景举例

在深度学习代码中,特别是在train.pytest.py中,argparse最常被使用。

因为在这些文件中,通常要对其他.py文件中定义的class或function进行调用,因此必然要传入大量的参数,如果不对这些参数进行集中编写,那么在冗长的代码中去找参数的定义位置或传参的位置将会十分麻烦。

argparse为用户提供了集中编写所需参数的机会,下面的使用教程中我会结合简单而具体的例子进行说明。

(三) 具体使用流程
  • 1.创建一个解析器

即创建 ArgumentParser() 对象 。

1
parser = argparse.ArgumentParser(description='test')

description:大多数对 ArgumentParser 构造方法的调用都会使用 description= 关键字参数

这个参数简要描述这个程度做什么以及怎么做。

在帮助消息中,这个描述会显示在命令行用法字符串和各种参数的帮助消息之间。

  • 2.添加参数

即调用 add_argument() 方法添加参数 。

1
2
3
4
5
parser.add_argument('--binary', action='store_true', default=False, 
help='action=store_true表示默认为False,当在命令行中使用--binary时自动变为True')
parser.add argument('--number', type=int, default=6help='普通数据,type可指定类型.')

parser.add argument('--epochs', type=int, default=300, help='Number of epochs to train.')

这里说一下如何定义参数的格式

ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])

  • name or flags:选项字符串的名字或者列表,例如 foo 或者 -f, —foo; action:命令行遇到参数时的动作,默认值是 store; store_const:表示赋值为const;
  • default :不指定参数时的默认值。
  • type:命令行参数应该被转换成的类型;
  • choices:参数可允许的值的一个容器;
  • nargs :应该读取的命令行参数个数,可以是具体的数字,或者是?号,当不指定值时对于 Positional argument 使用 default,对于 Optional argument 使用 const;或者是 * 号,表示 0 或多个参数;或者是 + 号表示 1 或多个参数。
  • required:可选参数是否可以省略 (仅针对可选参数)。
  • help:参数的帮助信息,当指定为 argparse.SUPPRESS 时表示不显示该参数的帮助信息.
  • metavar:在 usage 说明中的参数名称,对于必选参数默认就是参数名称,对于可选参数默认是全大写的参数名称
  • dest:解析后的参数名称,默认情况下,对于可选参数选取最长的名称,中划线转换为下划线.
  • const:action 和 nargs 所需要的常量值。
  • append:将遇到的值存储成列表,也就是如果参数重复则会保存多个值; append_const:将参数规范中定义的一个值保存到一个列表;
  • count:存储遇到的次数;此外,也可以继承 argparse.Action 自定义参数解析;
  • 3.解析参数

即使用 parse_args() 解析添加的参数。

1
args = parser.parse_args()
(四) 简单而具体的例子

例如我现在有一个.py文件,我现在定义了好多好多函数(为了方便我只定义了两个),我现在需要集中管理我传入的参数,使用argparse就会非常方便,对于本.py文件中的传参一目了然。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import argparse

parser = argparse.ArgumentParser(description='test')

parser.add_argument('--spring' ,action='store_true', default=False, help='nothing.')
parser.add_argument('--summer', type=int, default=6, help='num.')
parser.add_argument('--fa11', type=int, default=11, help='num.')
parser.add argument('--winter', type=int, default=100, help='Number of epochs to train.')

args = parser.parse_args()
# FLAGs,unparsed = parser.parse_known_args() 这种解析方法用的比较少,有兴趣可以了解一下

def sum_function(num2sum_1, num2sum_2):
sum_result = num2sum_1+num2sum_2
return sum_result

def multiply_function(num2multiply_1, num2multiply_2):
multiply_result = num2multiply_1*num2multiply_2
return multiply_result

print('args.spring的值是{}'.format(args.spring))
print('args.summer的值是{}'.format(args.summer))
print(sum_function(args.summer,args.fall))
print(multiply_function(args.summer,args.winter))

# 运行结果
# args.spring的值是False
# args.summer的值是6
# 17
# 600

你可以发现,对本文件中的函数进行传参,无论有多少参数需要传,我们只要在argparse中写好需要传的参数,在传参时传入args.参数名,需要修改传参值时,统一在argparse中进行修改即可,这样就方便了参数的管理。

(五) 如何修改参数值
  • 第一,对于有default的参数,直接修改default的值即可;
  • 第二,用命令行运行,例如在上面举例的程序,我如果想把summer的值改为10,fall的值改为20,那么命令行指令就是:python train.py —summer 10 —fall 20;如果我同时还想让spring的值成为True,那么命令行指令为:python train.py —summer 10 —fall 20 —spring
  • 第三,在Edit Configurations中进行配置,然后run即可:

image.png

  • 在 Python 的 argparse 模块中,位置参数不能使用 default 参数。因为定位参数是必需的,它们必须始终由用户提供,而不能使用默认值。
  • 在 Python 的 argparse 模块中,位置参数不能使用action参数,action="store_true" 用于创建布尔开关,但它不适用于必需的位置参数。位置参数不应该使用 action="store_true"

参考笔记:E:\A.毕业设计\前期基础知识学习\01-Python基础课件.pdf

  • Copyrights © 2015-2024 wjh
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信