第三章 流程控制语句3.1 简介3.2 条件判断语句(if 语句)3.2.1 if 语句3.2.2 input 函数3.2.3 if-else 语句3.2.4 if-elif-else 语句3.2.5 if 练习3.3 循环语句(while 语句 + for 语句)3.3.1 while 循环3.2.2 while 练习3.4 循环嵌套3.5 break 和 continue3.6 质数练习的优化3.7 小游戏 《唐僧大战白骨精》第四章 序列4.1 列表(list)的简介4.2 列表的切片4.3 通用操作4.4 序列(sequence)4.5 修改列表的元素4.6 列表中的方法4.7 遍历列表(list)4.8 EMS 项目练习4.9 range() 函数4.10 元组(tuple)4.11 可变对象--可变的是对象的值4.12 字典4.12.1 字典的使用4.12.2 字典的遍历4.13 集合4.14 集合的运算
第三章 流程控制语句
3.1 简介
Python 代码在执行时是按照自上向下顺序执行的。
通过流程控制语句,可以改变程序的执行顺序,也可以让指定的程序反复执行多次。
流程控制语句分成两大类:条件判断语句 + 循环语句
3.2 条件判断语句(if 语句)
3.2.1 if 语句
if 语句--示例代码:
# 条件判断语句(if语句)
# 语法:if 条件表达式 :
# 代码块
# 执行的流程:if 语句在执行时,会先对条件表达式进行求值判断:
# 如果为 True,则执行 if 后的语句
# 如果为 False,则不执行
# 默认情况下,if 语句只会控制紧随其后的那条语句,如果希望 if 可以控制多条语句,则可以在 if 后跟着一个代码块。
# 代码块:
# 代码块中保存着一组代码,同一个代码块中的代码,要么都执行要么都不执行。
# 代码块就是一种为代码分组的机制。
# 如果要编写代码块,语句就不能紧随在:后边,而是要写在下一行。
# 代码块以缩进开始,直到代码恢复到之前的缩进级别时结束。
# 鲁迅说过:
# 世上本来没有路,走的人多了自然就有了!
# xxxx...
# yyyy...
# 缩进有两种方式,一种是使用 tab 键,一种是使用空格(四个)
# Python 的官方文档中推荐我们使用空格来缩进
# Python 代码中使用的缩进方式必须统一
# sublime Text 3 中设置将 tab 键转换成空格:"translate_tabs_to_spaces": true,
# if False : print('你猜我出来么?')
num = 10
# if num > 10 : print('num比10大!')
# print('谁也管不了我')
if False :
print(123)
print(456)
print(789)
print(101112)
# print('hello')
# 可以使用【逻辑运算符】来连接多个条件:
# 如果希望所有条件同时满足,则需要使用 and
# 如果希望只要有一个条件满足即可,则需要使用 or
num = 28
# if num > 10 and num < 20 :
# print('num比10大,num比20小!')
# if 10 < num < 20 :
# print('num比10大,num比20小!')
# 在命令行让用户输入一个用户名,获取用户输入,并进行判断:
# 如果用户输入的用户名是 admin,则显示欢迎管理员光临
# 如果用户输入的是其他的用户名,则什么也不做
3.2.2 input 函数
input 函数--示例代码:
# input() 函数
# 该函数用来获取用户的输入
# 也可以用于暂时阻止程序结束
# input() 调用后,程序会立即暂停,等待用户输入
# 用户输入完内容以后,点击回车程序才会继续向下执行
# 用户输入完成以后,其所输入的的内容会以返回值的形式返回
# 注意:input() 返回值是一个字符串
# input() 函数中可以设置一个字符串作为参数,这个字符串将会作为提示文字显示
# a = input('请输入任意内容:')
# print('用户输入的内容是:', a)
# 获取用户输入的用户名
username = input('请输入你的用户名:')
# 判断用户名是否是 admin
if username == 'admin' :
print('欢迎管理员光临!')
3.2.3 if-else 语句
if-else 语句--示例代码:
# 让用户在控制台中输入一个年龄
# age = int(input('请输入你的年龄:'))
# 如果用户的年龄大于18岁,则显示你已经成年了
# if age >= 18 :
# print('你已经成年了~~~')
# if-else 语句
# 语法:
# if 条件表达式 :
# 代码块
# else :
# 代码块
# 执行流程:
# if-else 语句在执行时,先对 if 后的条件表达式进行求值判断
# 如果为 True,则执行 if 后的代码块
# 如果为 False,则执行 else 后的代码块
age = 7
if age > 17 :
print('你已经成年了~~~')
else :
print('你还未成年~~~')
3.2.4 if-elif-else 语句
if-elif-else 语句--示例代码:
# if-elif-else 语句
# 语法:
# if 条件表达式 :
# 代码块
# elif 条件表达式 :
# 代码块
# elif 条件表达式 :
# 代码块
# elif 条件表达式 :
# 代码块
# else :
# 代码块
#
# 执行流程:
# if-elif-else 语句在执行时,会自上向下依次对条件表达式进行求值判断:
# 如果表达式的结果为 True,则执行当前代码块,然后语句结束
# 如果表达式的结果为 False,则继续向下判断,直到找到 True 为止
# 如果所有的表达式都是 False,则执行 else 后的代码块
# if-elif-else 中只会有一个代码块会执行!!!
# 最后一个 else 可以省略。
age = 210
# if age > 200 :
# print('活着可真没劲呢!') # 只执行这一个代码块
# elif age > 100 :
# print('你也是老大不小了!')
# elif age >= 60 :
# print('你已经退休了!')
# elif age >= 30 :
# print('你已经是中年了!')
# elif age >= 18 :
# print('你已经成年了!')
# else :
# print('你还是个小孩!')
age = 68
if age >= 18 and age < 30 :
print('你已经成年了!')
elif age >= 30 and age < 60 :
print('你已经中年了!')
elif age >= 60 :
print('你已经退休了!')
3.2.5 if 练习
练习1:
编写一个程序,获取一个用户输入的整数。然后通过程序显示这个数是奇数还是偶数。
# 获取用户输入的整数
num = int(input('请输入一个任意的整数:'))
# # 显示num是奇数还是偶数
if num % 2 == 0 :
print(num, "是偶数")
else :
print(num, '是奇数')
练习2:
编写一个程序,检查任意一个年份是否是闰年。
如果一个年份可以被4整除不能被100整除,或者可以被400整除,这个年份就是闰年。
year = int(input('请输入一个任意的年份:'))
# 检查这个年份是否是闰年
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) :
print('是闰年')
else :
print('不是闰年')
练习3:
我家的狗5岁了,5岁的狗相当于多大年龄的人呢?
其实非常简单,狗的前两年每一年相当于人类的10.5岁,然后每增加一年就增加四岁。
那么5岁的狗相等于人类的年龄就应该是 10.5 + 10.5 + 4 + 4 + 4 = 33 岁
编写一个程序,获取用户输入的狗的年龄,然后通过程序显示其相当于人类的年龄。
如果用户输入负数,请显示一个提示信息。
# 检查用户输入的是否是负数
if dog_age < 0 :
print('你的输入不合法!')
# 如果狗的年龄在两岁以下(包含两岁)
elif dog_age <= 2 :
# 直接将当前的年龄乘以10.5
like_person_age = dog_age * 10.5
# 如果狗的年龄在两岁以上
else :
# 计算前两岁相当于人类的年纪
like_person_age = 2 * 10.5
# 计算超过两岁的部分相当于人类的年纪,并进行相加
like_person_age += ( dog_age - 2 ) * 4
if dog_age > 0 :
print(dog_age, '岁的狗,年纪相当于', like_person_age, '岁的人')
# --------------------改进版本--------------------
dog_age = float(input('请输入狗的年龄:'))
like_person_age = 0
# 在if也可以嵌套if,代码块是可以嵌套的,每增加一个缩进的级别,代码块就低一级
# 检查用户的输入是否合法
if dog_age > 0 :
# 如果狗的年龄在两岁以下(包含两岁)
if dog_age <= 2 :
# 直接将当前的年龄乘以10.5
like_person_age = dog_age * 10.5
# 如果狗的年龄在两岁以上
else :
# 计算前两岁相当于人类的年纪
like_person_age = 2 * 10.5
# 计算超过两岁的部分相当于人类的年纪,并进行相加
like_person_age += ( dog_age - 2 ) * 4
print(dog_age, '岁的狗,年纪相当于', like_person_age, '岁的人')
else :
print('请输入一个合法的年龄!')
# --------------------只使用 if 语句--------------------
dog_age = float(input('请输入狗的年龄:'))
like_person_age = 0
if 0 <= dog_age <= 2 :
like_person_age = dog_age * 10.5
print(dog_age, '岁的狗,年纪相当于', like_person_age, '岁的人')
if dog_age > 2 :
like_person_age = 2 * 10.5
like_person_age += ( dog_age - 2 ) * 4
print(dog_age, '岁的狗,年纪相当于', like_person_age, '岁的人')
if dog_age < 0 :
print('请输入一个合法的年龄!')
练习4:
从键盘输入小明的期末成绩:
当成绩为 100 时,'奖励一辆 BMW'
当成绩为 [80-99] 时,'奖励一台 iphone'
当成绩为 [60-79] 时,'奖励一本参考书'
其他时,什么奖励也没有
# 获取小明的成绩
score = float(input('请输入你的期末成绩(0-100):'))
# 打印分割线
print("="*40)
# 检查用户的输入是否合法
if 0 <= score <= 100 :
# 判断发给的奖励
if score == 100 :
print('宝马,拿去玩!')
elif score >= 80 :
print('苹果手机,拿去玩!')
elif score >= 60 :
print('参考书,拿去玩!')
else :
print('棍子一根!')
else :
# 用户输入的不合法,弹出一个友好提示
print('你输入的内容不合法,拉出去毙了!')
练习5:
大家都知道,男大当婚,女大当嫁。那么女方家长要嫁女儿,当然要提出一定的条件:
高:180cm 以上; 富:1000 万以上; 帅:500 以上;
如果这三个条件同时满足,则:'我一定要嫁给他'
如果三个条件有为真的情况,则:'嫁吧,比上不足,比下有余。'
如果三个条件都不满足,则:'不嫁!'
height = float(input('请输入你的身高(厘米):'))
money = float(input('请输入你的财富(万):'))
face = float(input('请输入你的颜值(平方厘米):'))
# 判断到底嫁不嫁
# 如果这三个条件同时满足,则:'我一定要嫁给他'
if height > 180 and money > 1000 and face > 500 :
print('我一定要嫁给他!')
# 如果三个条件有为真的情况,则:'嫁吧,比上不足,比下有余。'
elif height > 180 or money > 1000 or face > 500 :
print('嫁吧,比上不足,比下有余。')
# 如果三个条件都不满足,则:'不嫁!'
else :
print('不嫁!')
3.3 循环语句(while 语句 + for 语句)
3.3.1 while 循环
# 循环语句
# 循环语句可以使指定的代码块重复指定的次数
# 循环语句分成两种,while 循环 和 for 循环
# while 循环
# 语法:
# while 条件表达式 :
# 代码块
# else :
# 代码块
# 执行流程:
# while 语句在执行时,会先对 while 后的条件表达式进行求值判断:
# 如果判断结果为 True,则执行循环体(代码块),
# 循环体执行完毕,继续对条件表达式进行求值判断,以此类推,
# 直到判断结果为 False,则循环终止,如果循环有对应的 else,则执行 else 后的代码块。
# 条件表达式恒为 True 的循环语句,称为死循环,它会一直运行,慎用!
# while True :
# print('hello')
# 循环的三个要件(表达式):
# 初始化表达式:通过初始化表达式初始化一个变量
# i = 0
# 条件表达式:条件表达式用来设置循环执行的条件
# while i < 10 :
# print(i)
# # 更新表达式:修改初始化变量的值
# i += 1
# 创建一个执行十次的循环
i = 0
while i < 10 :
i += 1
print(i, 'hello')
else :
print('else 中的代码块')
3.2.2 while 练习
练习1:
求 100 以内所有的奇数之和。
# 求 100 以内所有的奇数之和。
i = 0
# 创建一个变量,用来保存结果
result = 0
while i < 100 :
i += 1
# 判断i是否是奇数
if i % 2 != 0 :
result += i
print('result =', result)
练习2:
求 100 以内所有 7 的倍数之和,以及个数。
# 求 100 以内所有7的倍数之和,以及个数。
i = 7
# 创建一个变量,来保存结果
result = 0
# 创建一个计数器,用来记录循环执行的次数,计数器就是一个变量,专门用来记录次数的变量
count = 0
while i < 100 :
# 为计数器加 1
count += 1
result += i
i += 7
print('总和为:', result, '总数量为:', count)
练习3:
水仙花数是指一个 n 位数(n ≥ 3),它的每个位上的数字的 n 次幂之和等于它本身(例如:13 + 53 + 3**3 = 153)。
求 1000 以内所有的水仙花数。
# 获取 1000 以内的三位数
i = 100
while i < 1000:
# 假设:i的百位数是a,十位数是b,个位数是c
# 求i的百位数
a = i // 100 # 首位:取商
# 求i的十位数
# b = i // 10 % 10 # 中间位:先取商再取余
b = (i - a * 100) // 10
# 求i的个位数字
c = i % 10 # 末位:取余
# print(i, a, b, c)
# 判断 i 是否是水仙花数
if a**3 + b**3 + c**3 == i :
print(i)
i += 1
练习4:
获取用户输入的任意数,判断其是否是质数。质数是只能被 1 和它自身整除的数,1 不是质数也不是合数。--使用逆向思维的方式。
# 获取用户输入的任意数,判断其是否是质数。
num = int(input('输入一个任意的大于1的整数:'))
# 判断 num 是否是质数,只能被1和它自身整除的数就是质数。1 不是质数也不是合数。
# 获取到所有的可能整除 num 的整数
i = 2
# 创建一个变量,用来记录 num 是否是质数,默认认为 num 是质数
flag = True
while i < num :
# 判断 num 能否被 i 整除
# 如果 num 能被 i 整除,则说明 num 一定不是质数
if num % i == 0 :
# 一旦进入判断,则证明 num 不是质数,则需要将 flag 修改为 False
flag = False
i += 1
if flag :
print(num, '是质数')
else :
print(num, '不是质数')
3.4 循环嵌套
# 在控制台中打印如下图形
# *****
# *****
# *****
# *****
# *****
# 创建一个循环来控制图形的高度
# 循环嵌套时,外层循环没执行一次,内存循环就要执行一圈
# i = 0
# while i < 5 :
# # 创建一个内层循环来控制图形的宽度
# j = 0
# while j < 5 :
# print("* ", end = '') # 不换行
# j += 1
# print()
# i += 1
#
# * j < 1 i = 0
# ** j < 2 i = 1
# *** j < 3 i = 2
# **** j < 4 i = 3
# ***** j < 5 i = 4
#
# *****
# ****
# ***
# **
#
i = 0
while i < 5 :
j = 0
while j < i + 1 :
print("* ", end = '')
j += 1
print()
i += 1
i = 0
while i < 5 :
j = 0
while j < 5 - i :
print("* ", end = '')
j += 1
print()
i += 1
练习1:
打印 99 乘法表。
i = 0
while i < 9 :
i += 1
j = 0
while j < i :
j += 1
print(f"{j} * {i} = {i * j} ", end = '')
print()
输出结果如下:
1 * 1 = 1
1 * 2 = 2 2 * 2 = 4
1 * 3 = 3 2 * 3 = 6 3 * 3 = 9
1 * 4 = 4 2 * 4 = 8 3 * 4 = 12 4 * 4 = 16
1 * 5 = 5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25
1 * 6 = 6 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36
1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49
1 * 8 = 8 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64
1 * 9 = 9 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81
练习2:
求 100 以内所有的质数。
打印 99 乘法表。
# 求100以内所有的质数
# 创建一个循环,求 1-100 以内所有的数
i = 2
while i <= 100 :
# 创建一个变量,记录 i 的状态,默认认为 i 是质数
flag = True
# 判断 i 是否是质数
# 获取所有可能成为 i 的因数的数
j = 2
while j < i :
# 判断 i 能否被 j 整除
if i % j == 0:
# i 能被 j 整除,证明 i 不是质数,修改 flag 为 False
flag = False
j += 1
# 验证结果并输出
if flag :
print(i)
i += 1
3.5 break 和 continue
# break
# break 可以用来立即退出整个循环语句(包括 else)
# continue
# continue 可以用来跳过当次循环
# break 和 continue 都是只对离他最近的循环起作用
# pass
# pass 是用来在判断或循环语句中占位的
# i = 0
# while i < 5 :
# if i == 3 :
# break
# print(i)
# i += 1
# else :
# print('循环结束')
# i = 0
# while i < 5 :
# i += 1
# if i == 2 :
# continue
# print(i)
# else :
# print('循环结束')
i = 0
if i < 5 :
pass
3.6 质数练习的优化
# 模块,通过模块可以对 Python 进行扩展
# 引入一个 time 模块,来统计程序执行的时间
from time import *
# time() 函数可以用来获取当前的时间,返回的单位是秒
# 优化前:
# 10000个数 12.298秒
# 100000个数 没有结果
# 第一次优化
# 10000个数 1.577秒
# 100000个数 170.645秒
# 第二次优化
# 10000个数 0.068秒
# 100000个数 1.646秒
# 和数36的因数
# 2 18
# 3 12
# 4 9
# 6 6
#
# 求 100 以内所有的质数。
# 获取程序开始的时间
begin = time()
i = 2
while i <= 100000 :
flag = True
j = 2
while j <= i ** 0.5 : # 第二次优化,因为因数都是成对出现的,此时需要带上等号
if i % j == 0 :
flag = False
# 一旦进入判断,则证明 i 一定不是质数,此时内层循环没有继续执行的必要(即只要有一个(除了1和它自身外)数能被i整除,那么 i 一定不是质数)
# 使用 break 来退出内层的循环
break # 第一次优化
j += 1
if flag :
# print(i)
pass
i += 1
# 获取程序结束的时间
end = time()
# 计算程序执行的时间
print("程序执行花费了:"end - begin , "秒")
3.7 小游戏 《唐僧大战白骨精》
1、身份选择
① 显示提示信息
欢迎光临 xxx 游戏!
请选择你的身份:
1.xxx
2.xxx
请选择:x
② 根据用户选择来分配身份(显示不同的提示消息)
1.---
2.---
3.---
2、游戏进行
① 显示玩家的基本信息(攻击力 生命值)
② 显示玩家可以进行的操作:
1、练级
- 提升玩家的攻击力和生命值
2、打 BOSS
- 玩家对 BOSS 进行攻击,玩家要攻击 BOSS,BOSS 对玩家进行反击
- 计算 BOSS 是否被玩家消灭,玩家是否被 BOSS 消灭
- 游戏结束
3、逃跑
- 退出游戏,显示提示信息,游戏结束!
版本1.0 代码:
# 显示欢迎信息
print('-'*20, '欢迎光临《唐僧大战白骨精》', '-'*20)
# 显示身份选择的信息
print('请选择你的身份:')
print(' 1.唐僧')
print(' 2.白骨精')
# 游戏的身份选择
player_choose = input('请选择[1-2]:') # input 函数返回的字符串
# 打印一条分割线
print('-'*66)
# 根据用户的选择来显示不同的提示信息
if player_choose == '1':
# 选择 1
print('你已经选择了1,你将以->唐僧<-的身份来进行游戏!')
elif player_choose == '2':
# 选择 2
print('你竟然选择了白骨精,太不要脸了,你将以->唐僧<-的身份来进行游戏!')
else :
# 选择 3
print('你的输入有误,系统将自动分配身份,你将以->唐僧<-的身份来进行游戏!')
# 进入游戏
# 创建变量,来保存玩家的生命值和攻击力
player_life = 2 # 生命值
player_attack = 2 # 攻击力
# 创建变量,保存 boss 的生命值和攻击力
boss_life = 10
boss_attack = 10
# 打印一条分割线
print('-'*66)
# 显示玩家的信息(攻击力、生命值)
print(f'唐僧,你的生命值是 {player_life},你的攻击力是 {player_attack}')
# 由于游戏选项是需要反复显示的,所以必须将其编写到一个循环中
while True :
# 打印一条分割线
print('-'*66)
# 显示游戏选项,游戏正式开始
print('请选择你要进行的操作:')
print(' 1.练级')
print(' 2.打BOSS')
print(' 3.逃跑')
game_choose = input('请选择要做的操作[1-3]:')
# 处理用户的选择
if game_choose == '1' :
# 增加玩家的生命值和攻击力
player_life += 2
player_attack += 2
# 显示玩家的最新信息
# 打印一条分割线
print('-'*66)
# 显示玩家的信息(攻击力、生命值)
print(f'恭喜你升级了!你现在的生命值是 {player_life},你的攻击力是 {player_attack}')
elif game_choose == '2' :
# 玩家攻击 boss
# 减去 boss 的生命值,减去的生命值应该等于玩家的攻击力
boss_life -= player_attack
# 打印一条分割线
print('-'*66)
print('->唐僧<- 攻击了 ->白骨精<-')
# 检查 boss 是否死亡
if boss_life <= 0 :
# boss 死亡,player 胜利,游戏结束
print(f'->白骨精<-受到了 {player_attack} 点伤害,重伤不治死了,->唐僧<-赢得了胜利!')
# 游戏结束
break
# boss 要反击玩家
# 减去玩家的生命值,减去的玩家生命值应该等于 boss 的攻击力
player_life -= boss_attack
print(' ->白骨精<- 攻击了 ->唐僧<-')
# 检查玩家是否死亡
if player_life <= 0 :
# 玩家死亡
print(f'你受到了 {boss_attack} 点伤害,重伤不治死了!GAME OVER')
# 游戏结束
break
elif game_choose == '3' :
# 打印一条分割线
print('-'*66)
# 逃跑,退出游戏
print('->唐僧<-一扭头,撒腿就跑!GAME OVER')
break
else :
# 打印一条分割线
print('-'*66)
print('你的输入有误,请重新输入!')
第四章 序列
4.1 列表(list)的简介
- 列表是 Python 中的一个对象
对象(object)就是内存中专门用来存储数据的一块区域
- 之前我们学习的对象,像数值,它只能保存一个单一的数据
- 列表中可以保存多个有序的数据(元素可重复,顺序指的是 添加的顺序)
- 列表是用来存储对象的对象
- 列表的使用:
1.列表的创建
2.操作列表中的数据
列表--示例代码:
# 创建列表,通过[]来创建列表
my_list = [] # 创建了一个空列表
# print(my_list, type(my_list)) # [] <class 'list'>
# 列表存储的数据,我们称为元素
# 一个列表中可以存储多个元素,也可以在创建列表时,来指定列表中的元素
my_list = [10] # 创建一个只包含一个元素的列表
# 当向列表中添加多个元素时,多个元素之间使用,隔开
my_list = [10, 20, 90, 40, 50] # 创建了一个包含有5个元素的列表
# 列表中可以保存任意的对象
my_list = [10, 'hello', True, None, [1, 2, 3], print]
print(my_list) # [10, 'hello', True, None, [1, 2, 3], <built-in function print>]
# 列表中的对象都会按照插入的顺序存储到列表中:
# 即第一个插入的对象保存到第一个位置,第二个保存到第二个位置
# 我们可以通过索引(index)来获取列表中的元素:
# 索引是元素在列表中的位置,列表中的每一个元素都有一个索引
# 索引是从 0 开始的整数,列表第一个位置索引为 0,第二个位置索引为 1,第三个位置索引为 2,以此类推
my_list = [10, 20, 90, 40, 50]
# 通过索引获取列表中的元素
# 语法:my_list[索引] my_list[0]
# print(my_list[4])
# 如果使用的索引超过了最大的范围,会抛出异常,如下:
# print(my_list[5]) # IndexError: list index out of range
# 获取列表的长度,列表中元素的个数
# len()函数,通过该函数可以获取列表的长度
# 获取到的长度的值,是列表的最大索引 + 1
print(len(my_list)) # 5
4.2 列表的切片
# 切片
# 切片指从现有列表中,获取一个子列表
# 创建一个列表,一般创建列表时,变量的名字会使用复数
stus = ['孙悟空', '猪八戒', '沙和尚', '唐僧', '蜘蛛精', '白骨精']
# 列表的索引可以是负数
# 如果索引是负数,则从后向前获取元素,-1 表示倒数第一个,-2 表示倒数第二个,以此类推
# print(stus[-2])
# 通过切片来获取指定的元素
# 语法:列表[起始:结束]
# 通过切片获取元素时,会包括起始位置的元素,不会包括结束位置的元素
# 做切片操作时,总会返回一个新的列表,不会影响原来的列表
# 起始和结束位置的索引都可以省略不写
# 如果省略结束位置,则会一直截取到最后
# 如果省略起始位置,则会从第一个元素开始截取
# 如果起始位置和结束位置全部省略,则相当于创建了一个列表的副本
# print(stus[1:2]) # 包头不包尾
# print(stus[1:])
# print(stus[:3])
# print(stus[:])
# print(stus)
# 语法:列表[起始:结束:步长]
# 步长表示,每次获取元素的间隔,默认值是1
# print(stus[0:5:3])
# 步长不能是 0,但是可以是负数
# print(stus[::0]) # ValueError: slice step cannot be zero
# 如果是负数,则会从列表的后部向前边取元素
print(stus[::-1])
正数和负数索引:
4.3 通用操作
# + 和 *
# + 可以将两个列表拼接为一个列表
my_list = [1, 2, 3] + [4, 5, 6] # [1, 2, 3, 4, 5, 6]
# * 可以将列表重复指定的次数
my_list = [1, 2, 3] * 3 # [1, 2, 3, 1, 2, 3, 1, 2, 3]
# print(my_list)
# 创建一个列表
stus = ['孙悟空', '猪八戒', '沙和尚', '唐僧', '蜘蛛精', '白骨精', '沙和尚', '沙和尚']
# in 和 not in
# in 用来检查指定元素是否存在于列表中
# 如果存在,返回 True,否则返回 False
# not in 用来检查指定元素是否不在列表中
# 如果不在,返回 True,否则返回 False
# print('牛魔王' not in stus)
# print('牛魔王' in stus)
# len() 获取列表中的元素的个数
# min() 获取列表中的最小值
# max() 获取列表中的最大值
arr = [10, 1, 2, 5, 100, 77]
# print(min(arr), max(arr))
# 两个方法(method),方法和函数基本上是一样,只不过方法必须通过 对象.方法() 的形式调用
# xxx.print() 方法实际上就是和对象关系紧密的函数
# s.index() 获取指定元素在列表中的第一次出现时索引
# print(stus.index('沙和尚'))
# index() 的第二个参数,表示查找的起始位置,第三个参数,表示查找的结束位置(包头不包尾)
# print(stus.index('沙和尚', 3, 7))
# 如果要获取列表中没有的元素,会抛出异常
# print(stus.index('牛魔王')) # ValueError: '牛魔王' is not in list
# s.count() 统计指定元素在列表中出现的次数
print(stus.count('牛魔王'))
4.4 序列(sequence)
- 序列是 Python 中最基本的一种数据结构
数据结构指计算机中数据存储的方式
- 序列用于保存一组有序的数据,所有的数据在序列当中都有一个唯一的位置(索引)
并且序列中的数据会按照添加的顺序来分配索引
- 序列的分类:
可变序列(序列中的元素可以改变):
> 列表(list)
不可变序列(序列中的元素不能改变):
> 字符串(str)
> 元组(tuple)
上面所讲的所有操作都是序列的通用操作。
4.5 修改列表的元素
# 创建一个列表
stus = ['孙悟空', '猪八戒', '沙和尚', '唐僧', '蜘蛛精', '白骨精']
# print("修改前:", stus)
# 修改列表中的元素
# 直接通过索引来修改元素
stus[0] = 'sunwukong'
stus[2] = '哈哈'
# 通过 del 来删除元素
del stus[2] # 删除索引为2的元素
# print('修改后:', stus)
stus = ['孙悟空', '猪八戒', '沙和尚', '唐僧', '蜘蛛精', '白骨精']
# print("修改前:", stus)
# 通过切片来修改列表
# 在给切片进行赋值时,只能使用序列
# stus[0:2] = ['牛魔王', '红孩儿'] # 使用新的元素替换旧元素
# stus[0:2] = ['牛魔王', '红孩儿', '二郎神'] # 可以传多个
# stus[0:0] = ['牛魔王'] # 向索引为0的位置插入新的元素
# 当设置了步长时,要替换的序列中元素的个数必须和切片中切出来的元素的个数一致
# stus[::2] = ['牛魔王', '红孩儿'] # 报错:切片中切出来的元素的个数是3个元素,而要替换的元素的个数是2个
# stus[::2] = ['牛魔王', '红孩儿', '二郎神'] # 正确
# 通过切片来删除元素
# del stus[0:2]
# del stus[::2]
# stus[1:3] = []
# print('修改后:', stus)
# 以上操作,只适用于可变序列
s = 'hello'
# s[1] = 'a' # 报错:不可变序列,无法通过索引来修改
# 可以通过 list() 函数将其他的序列转换为list
s = list(s)
print(s)
4.6 列表中的方法
# 列表的方法
stus = ['孙悟空', '猪八戒', '沙和尚']
# print('原列表:', stus)
# append()
# 向列表的最后添加一个元素
# stus.append('唐僧')
# insert()
# 向列表的指定位置插入一个元素
# 参数:
# 1.要插入的位置
# 2.要插入的元素
# stus.insert(2, '唐僧')
# extend()
# 使用新的序列来扩展当前序列
# 需要一个序列作为参数,它会将该序列中的元素添加到当前列表中
# stus.extend(['唐僧', '白骨精'])
# stus += ['唐僧', '白骨精']
# clear()
# 清空序列(可变序列)
# stus.clear()
stus = ['孙悟空', '猪八戒', '沙和尚', '唐僧']
# pop()
# 根据索引删除并返回被删除的元素
# result = stus.pop(2) # 删除序列索引为2的元素
# result = stus.pop() # 删除序列最后一个元素
# print('result =', result)
# remove()
# 删除指定值的元素,如果相同值的元素有多个,则只会删除第一个元素
# stus.remove('猪八戒')
# reverse()
# 用来反转列表
# stus.reverse()
# sort()
# 用来对列表中的元素进行排序,默认是升序排列(从小到大)
# 如果需要降序排列,则需要传递一个 reverse=True 作为参数
my_list = list('asnbdnbasdabd')
my_list = [10, 1, 20, 3, 4, 5, 0, -2]
print('排序前', my_list)
my_list.sort(reverse=True)
print('排序后', my_list)
4.7 遍历列表(list)
# 遍历列表:指的就是将列表中的所有元素取出来
# 创建列表
stus = ['孙悟空', '猪八戒', '沙和尚', '唐僧', '白骨精', '蜘蛛精']
# 遍历列表
# print(stus[0])
# print(stus[1])
# print(stus[2])
# print(stus[3])
# 通过 while 循环来遍历列表
# i = 0
# while i < len(stus) :
# print(stus[i])
# i += 1
# 通过 for 循环来遍历列表
# 语法:
# for 变量 in 序列 :
# 代码块
# for 循环的代码块会执行多次,即序列中有几个元素就会执行几次
# 每执行一次就会将序列中的一个元素的值赋值给变量
# 所以我们可以通过变量,来获取列表中的元素
for s in stus :
print(s)
4.8 EMS 项目练习
- 做命令行版本的员工管理系统
- 功能:
四个:
1.查询
- 显示当前系统当中的所有员工
2.添加
- 将员工添加到当前系统中
3.删除
- 将员工从系统当中删除
4.退出
- 退出系统
- 员工信息要保存到哪里? 列表,在系统中应该有一个列表,专门用来保存所有员工信息的。
示例代码:
# 显示系统的欢迎信息
print('-'*20, '欢迎使用员工管理系统', '-'*20)
# 创建一个列表,用来保存员工信息,员工的信息以字符串的形式统一保存到列表
emps = ['孙悟空 18 男 花果山', '猪八戒 28 男 高老庄']
while True :
# 显示用户的选项
print(' 请选择要做的操作:')
print(' 1.查询员工')
print(' 2.添加员工')
print(' 3.删除员工')
print(' 4.退出系统')
user_choose = input('请选择要做的操作[1-4]:')
# 为了好看,打印分割线
print('-'*62)
# 根据用户的选择来做相关的操作
if user_choose == '1' :
# 查询员工
# 打印表头
print(' 序号 姓名 年龄 性别 地址')
# 创建一个变量,来表示员工的序号
n = 1
# 显示员工信息
for emp in emps :
print(f' {n} {emp}')
n += 1
elif user_choose == '2' :
# 添加员工
# 获取要添加员工的信息:姓名、年龄、性别、住址
emp_name = input('请输入员工姓名:')
emp_age = input('请输入员工年龄:')
emp_gender = input('请输入员工性别:')
emp_address = input('请输入员工住址:')
# 创建员工信息
emp = f'{emp_name} {emp_age} {emp_gender} {emp_address}'
# 显示提示信息
print('以下员工将会被添加到系统中')
print('-'*62)
print(' 姓名 年龄 性别 地址')
print(f' {emp}')
print('-'*62)
# 确认信息
user_confirm = input('是否确认该操作[Y/N]:')
if user_confirm == 'y' or user_confirm == 'Y' or user_confirm == 'yes' :
# 拼接字符串,插入列表中
emps.append(emp)
print('插入员工成功!')
else :
print('插入员工已取消!')
elif user_choose == '3' :
# 删除员工,根据员工的序号来删除员工
del_num = int(input('请输入要删除的员工序号:'))
del_index = del_num - 1
# 判断
if 0 <= del_index <= len(emps) - 1 :
# 显示提示信息
print('以下员工将会被删除')
print('-'*62)
print(' 序号 姓名 年龄 性别 地址')
print(f' {del_num} {emps[del_index]}')
print('-'*62)
# 确认信息
user_confirm = input('该操作不可恢复,是否确认[Y/N]:')
if user_confirm == 'y' or user_confirm == 'Y' or user_confirm == 'yes' :
# 拼接字符串,插入列表中
emps.pop(del_index)
print('删除员工成功!')
else :
print('删除员工已取消!')
else :
print('您的输入有误,请重新操作!')
elif user_choose == '4' :
print('欢迎使用,再见!')
input('点击回车键退出系统!')
break
else :
print('您的输入有误,请重新输入!')
# 为了好看,打印分割线
print('-'*62)
4.9 range() 函数
# range() 是一个函数,可以用来生成一个自然数的序列
r = range(5) # 生成一个这样的序列:[0, 1, 2, 3, 4]
r = range(0, 10, 2) # [0, 2, 4, 6, 8]
r = range(10, 0, -1) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
# 该函数需要三个参数
# 1.起始位置(可以省略,默认是 0)
# 2.结束位置
# 3.步长(可以省略,默认是 1)
# print(list(r))
# 通过 range() 可以创建一个执行指定次数的 for 循环
# for() 循环除了创建方式以外,其余的都和 while 一样,
# 包括 else、包括 break、continue 都可以在 for 循环中使用
# 并且 for 循环使用也更加简单
# 将之前使用 while 循环做的练习,再使用 for 循环完成一次!
for i in range(30) :
print(i)
# for s in 'hello' :
print(s)
4.10 元组(tuple)
# 元组 tuple
# 元组是一个不可变的序列
# 它的操作的方式基本上和列表是一致的
# 所以你在操作元组时,就把元组当成是一个不可变的列表就ok了
# 一般当我们希望数据不改变时,就使用元组,其余情况都使用列表
# 创建元组
# 使用()来创建元组
my_tuple = () # 创建了一个空元组
# print(my_tuple, type(my_tuple)) # () <class 'tuple'>
my_tuple = (1, 2, 3, 4, 5) # 创建了一个5个元素的元组
# 元组是不可变对象,不能尝试为元组中的元素重新赋值
# my_tuple[3] = 10 # 报错:TypeError: 'tuple' object does not support item assignment
# print(my_tuple[3])
# 当元组不是空元组时,括号可以省略
# 如果元组不是空元组,它里边至少要有一个元素,且该元素后面要有一个逗号
my_tuple = 10, 20, 30, 40
my_tuple = 40, # 注意逗号的存在
# print(my_tuple, type(my_tuple))
# 元组的解包(解构)
# 解包指就是将元组当中每一个元素都赋值给一个变量
my_tuple = 10, 20, 30, 40
a, b, c, d = my_tuple
# print("a =", a)
# print("b =", b)
# print("c =", c)
# print("d =", d)
a = 100
b = 300
print(a, b)
# 交换 a 和 b 的值,这时我们就可以利用元组的解包
a, b = b, a # b, a 等价于 (b, a)
print(a, b)
my_tuple = 10, 20, 30, 40
# 在对一个元组进行解包时,变量的数量必须和元组中的元素的数量一致
# 也可以在变量前边添加一个*,这样变量将会获取元组中所有剩余的元素
a, b, *c = my_tuple
a, *b, c = my_tuple
*a, b, c = my_tuple
# 不能同时出现两个或以上的*变量
# *a, *b, c = my_tuple # 报错:SyntaxError: two starred expressions in assignment
print('a =', a)
print('b =', b)
print('c =', c)
练习:
a, b, *c = [1, 2, 3, 4, 5, 6, 7]
a, b, *c = 'hello world'
print('a =', a)
print('b =', b)
print('c =', c)
4.11 可变对象--可变的是对象的值
- 每个对象中都保存了三个数据:
id(标识)
type(类型)
value(值)
- 列表就是一个可变对象
a = [1, 2, 3]
- a[0] = 10 (改对象)
- 这个操作是在通过变量去修改对象的值
- 这种操作不会改变变量所指向的对象
- 当我们去修改对象时,如果有其他变量也指向了该对象,则修改也会在其他的变量中体现
- a = [4, 5, 6] (改变量)
- 这个操作是在给变量重新赋值
- 这种操作会改变变量所指向的对象
- 为一个变量重新赋值时,不会影响其他的变量
- 一般只有在为变量赋值时才是修改变量,其余的都是修改对象。
图解如下:
示例代码:
# 可变对象
# a = [1, 2, 3]
# print('修改前:', a, id(a))
# # 通过索引修改列表对象的值
# a[0] = 10
# print('修改后:', a, id(a))
# 为变量重新赋值
# a = [4,5,6]
# print('修改后:', a , id(a))
a = [1, 2, 3]
b = a
# b[0] = 10
b = [10, 2, 3]
# print("a", a, id(a))
# print("b", b, id(b))
# == != 比较的是对象的值是否相等
# is 和 is not 比较的是对象的 id 是否相等(比较两个对象是否是同一个对象)
a = [1, 2, 3]
b = [1, 2, 3]
print(a, b)
print(id(a), id(b)) # 2133622547080 2133622547144
print(a == b) # True,a和b的值相等,使用 == 会返回 True
print(a is b) # False,a和b不是同一个对象,内存地址不同,使用 is 会返回 False
图解如下:
改对象的值会影响所有指向该对象的变量
一般只有在为变量赋值时才是修改变量
4.12 字典
字典简介:
- 字典属于一种新的数据结构,称为映射(mapping)
- 字典的作用和列表类似,都是用来存储对象的容器
- 列表存储数据的性能很好,但是查询数据的性能的很差
- 在字典中每一个元素都有一个唯一的名字,通过这个唯一的名字可以快速的查找到指定的元素
- 在查询元素时,字典的效率是非常快的
- 在字典中可以保存多个对象,每个对象都会有一个唯一的名字
这个唯一的名字,我们称其为键(key),通过 key 可以快速的查询 value
这个对象,我们称其为值(value)
所以字典,我们也称为叫做 键值对(key-value)结构
每个字典中都可以有多个键值对,而每一个键值对我们称其为一项(item)
字典--示例代码:
# 字典
# 使用 {} 来创建字典
d = {} # 创建了一个空字典
# print(d, type(d)) # {} <class 'dict'>
# 创建一个包含有数据的字典
# 语法:
# {key:value, key:value, key:value}
# 字典的值可以是任意对象
# 字典的键可以是任意的不可变对象(int、str、bool、tuple、...),但是一般我们都会使用 str
# 字典的键是不能重复的,如果出现重复的键,那么后边的键的值会替换前边的键的值
# d = {'name':'孙悟空', 'age':18, 'gender':'男', 'name':'sunwukong'}
d = {
'name':'孙悟空',
'age':18,
'gender':'男',
'name':'sunwukong'
}
# print(d, type(d))
# 需要根据键来获取值
# print(d['name'], d['age'], d['gender'])
# 如果使用了字典中不存在的键,会报错
# print(d['hello']) # KeyError: 'hello'
4.12.1 字典的使用
# 创建字典
# 使用 {}
# 语法:{k1:v1, k2:v2, k3:v3}
# 使用 dict() 函数来创建字典
# 每一个参数都是一个键值对,参数名就是键,参数值就是值(这种方式创建的字典,key 都是字符串)
d = dict(name='孙悟空', age=18, gender='男')
# 也可以将一个包含有双值子序列的序列转换为字典
# 双值序列,序列中只有两个值,比如:[1, 2] ('a', 3) 'ab'
# 子序列,如果序列中的元素也是序列,那么我们就称这个元素为子序列,比如:[(1, 2), (3, 5)]
d = dict([('name', '孙悟饭'), ('age', 18)])
# print(d, type(d))
# len() 获取字典中键值对的个数
# print(len(d))
# in 检查字典中是否包含指定的键
# not in 检查字典中是否不包含指定的键
# print('hello' in d)
# 获取字典中的值,根据键来获取值
# 语法:d[key]
# print(d['age'])
# n = 'name'
# print(d[n])
# 通过 [] 来获取值时,如果键不存在,会抛出异常 KeyError
# get(key[, default]) 该方法用来根据键来获取字典中的值
# 如果获取的键在字典中不存在,会返回 None
# 也可以指定一个默认值,来作为第二个参数,这样获取不到值时将会返回默认值
# print(d.get('name'))
# print(d.get('hello', '默认值'))
# 修改字典
# d[key] = value #如果 key 存在则覆盖,不存在则添加
d['name'] = 'sunwukong' # 修改字典的 key-value
d['address'] = '花果山' # 向字典中添加 key-value
# print(d)
# setdefault(key[, default]) # 可以用来向字典中添加 key-value
# 如果 key 已经存在于字典中,则返回 key 的值,不会对字典做任何操作
# 如果 key 不存在,则向字典中添加这个 key,并设置 value
result = d.setdefault('name', '猪八戒')
result = d.setdefault('hello', '猪八戒')
# print('result =', result)
# print(d)
# update([other])
# 将其他的字典中的 key-value 添加到当前字典中
# 如果有重复的 key,则后边的会替换到当前的
d1 = {'a':1, 'b':2, 'c':3}
d2 = {'d':4, 'e':5, 'f':6, 'a':7}
d1.update(d2)
# print(d1) # {'a': 7, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
------------------------------------------------------------------
# 删除,可以使用 del 来删除字典中的 key-value
del d1['a']
del d1['b']
# popitem()
# 随机删除字典中的一个键值对,一般都会删除最后一个键值对
# 删除之后,它会将删除的 key-value 作为返回值返回
# 返回的是一个元组,元组中有两个元素,第一个元素是删除的 key,第二个是删除的 value
# 当使用 popitem() 删除一个空字典时,会抛出异常 KeyError: 'popitem(): dictionary is empty'
# d1.popitem()
# result = d1.popitem()
# pop(key[, default])
# 根据 key 删除字典中的 key-value
# 会将被删除的 value 返回!
# 如果删除不存在的 key,会抛出异常
# 如果指定了默认值,再删除不存在的 key 时,不会报错,而是直接返回默认值
result = d1.pop('d')
result = d1.pop('z', '这是默认值')
# del d1['z']
# z 不存在时,也会报错
# result = d1.popitem()
# result = d1.popitem()
# result = d1.popitem()
# result = d1.popitem()
# clear() 用来清空字典
d1.clear()
# print('result =', result)
# print(d1)
# copy()
# 该方法用于对字典进行浅复制
# 复制以后的对象,和原对象是独立的,修改一个不会影响另一个
# 注意:浅复制会简单复制对象内部的值,如果值也是一个可变对象,这个可变对象不会被复制
d1 = {'a':1, 'b':2, 'c':3}
d2 = d1.copy()
# d1['a'] = 100
d1 = {'a':{'name':'孙悟空', 'age':18}, 'b':2, 'c':3}
d2 = d1.copy()
d2['a']['name'] = '猪八戒'
print('d1 =', d1, id(d1))
print('d2 =', d2, id(d2))
4.12.2 字典的遍历
# 遍历字典
# keys()
该方法会返回字典的所有的 key
# 该方法会返回一个序列,序列中保存字典的所有的键
d = {'name':'孙悟空', 'age':18, 'gender':'男'}
# 通过遍历 keys() 来获取所有的键
# for k in d.keys() :
# print(k, d[k])
# values()
# 该方法会返回一个序列,序列中保存字典的所有的值
# for v in d.values():
# print(v)
# items()
# 该方法会返回字典中所有的项
# 它会返回一个序列,序列中包含有双值子序列
# 双值分别是:字典中的 key 和 value
# print(d.items()) # dict_items([('name', '孙悟空'), ('age', 18), ('gender', '男')])
for k, v in d.items() :
print(k, '=', v)
# 元组的解包(解构)
# 解包指就是将元组当中每一个元素都赋值给一个变量
4.13 集合
集合的介绍:
- 集合和列表非常相似
- 不同点:
1.集合中只能存储不可变对象
2.集合中存储的对象是无序(不是按照元素的插入顺序保存的)
3.集合中不能出现重复的元素
集合--示例代码:
# 集合
# 使用 {} 来创建集合
s = {10, 3, 5, 1, 2, 1, 2, 3, 1, 1, 1, 1} # <class 'set'>
# s = {[1, 2, 3], [4, 6, 7]} # TypeError: unhashable type: 'list'
# 使用 set() 函数来创建集合
s = set() # 空集合
# 可以通过 set() 来将序列和字典转换为集合
s = set([1, 2, 3, 4, 5, 1, 1, 2, 3, 4, 5])
s = set('hello')
s = set({'a':1, 'b':2, 'c':3}) # 使用 set() 将字典转换为集合时,只会包含字典中的键
# 创建集合
s = {'a', 'b', 1, 2, 3, 1}
# 使用 in 和 not in 来检查集合中的元素
# print('c' in s)
# 使用 len() 来获取集合中元素的数量
# print(len(s))
# add() 向集合中添加元素
s.add(10)
s.add(30)
# update() 将一个集合中的元素添加到当前集合中
# update() 可以传递序列或字典作为参数,字典只会使用键
s2 = set('hello')
s.update(s2)
s.update((10, 20, 30, 40, 50)) # 参数是元组
s.update({10:'ab', 20:'bc', 100:'cd', 1000:'ef'}) # 参数是字典
# {1, 2, 3, 100, 40, 'o', 10, 1000, 'a', 'h', 'b', 'l', 20, 50, 'e', 30}
# pop() 随机删除并返回一个集合中的元素
# result = s.pop()
# remove() 删除集合中的指定元素
s.remove(100)
s.remove(1000)
# clear() 清空集合
s.clear()
# copy() 对集合进行浅复制
# print(result)
print(s, type(s))
4.14 集合的运算
# 在对集合做运算时,不会影响原来的集合,而是返回一个运算结果
# 创建两个集合
s1 = {1, 2, 3, 4, 5}
s2 = {3, 4, 5, 6, 7}
# & 交集运算
result = s1 & s2 # {3, 4, 5}
# | 并集运算
result = s1 | s2 # {1, 2, 3, 4, 5, 6, 7}
# - 差集
result = s1 - s2 # {1, 2}
# ^ 异或集:获取只在一个集合中出现的元素
result = s1 ^ s2 # {1, 2, 6, 7}
# <= 检查一个集合是否是另一个集合的子集
# 如果 a 集合中的元素全部都在 b 集合中出现,那么 a 集合就是 b 集合的子集,b 集合是 a 集合的超集
a = {1, 2, 3}
b = {1, 2, 3, 4, 5}
result = a <= b # True
result = {1, 2, 3} <= {1, 2, 3} # True
result = {1, 2, 3, 4, 5} <= {1, 2, 3} # False
# < 检查一个集合是否是另一个集合的真子集
# 如果超集 b 中含有子集 a 中所有元素,并且 b 中还有 a 中没有的元素,则 b 就是 a 的真超集,a 是 b 的真子集
result = {1, 2, 3} < {1, 2, 3} # False
result = {1, 2, 3} < {1, 2, 3, 4, 5} # True
# >= 检查一个集合是否是另一个的超集
# > 检查一个集合是否是另一个的真超集
print('result =', result)