一.pycharm使用入门
1.creat project
-
虚拟环境:基于系统环境copy的一个环境,python的版本是依据于系统环境的python版本
-
系统环境:
-
对比于用户来说,是不受制用户登录的限制,所有的用户都可以使用
-
对比于虚拟环境,是相互独立的,互不干扰--比如我在系统环境中安装了一个python的依赖包,虚拟环境是不会对应安装的(不存在的,需要单独去安装)
-
在pycharm项目中。可以随意更换项目所依赖的环境
-
所有的python项目都是需要依据环境来运行的--python脚本
-
项目和python环境是可以分开的,只不过是受制于python环境中的依赖包
-
项目的内容不要放在环境的目录下面
-
-
pycharm使用系统环境,不会去创建venv目录
pycharm创建项目之后
first:是命名的项目名称
vevn文件夹:虚拟环境的文件夹(不懂的话,千万不要乱动)
新建文件的时候,需要右键项目名称的文件夹,然后创建文件 -- 千万不要在venv目录下面创建文件
2.安装依赖包
-
pip install 依赖包
pip install 依赖包名称 -i 镜像源地址
安装在系统环境就在系统环境,虚拟环境没有;安装在虚拟环境同理
如果需要安装历史版本,就采用以下方式:
-
点击右边的 Specify version 勾选框
-
点击右边的下拉框按钮
-
选择所需要的版本
-
点击Install Package
注意:如果网络不太好的情况下,可能出不来版本信息,那么就采用命令下载的方式
国内镜像源:
https://pypi.douban.com/simple/ 豆瓣 https://mirrors.aliyun.com/pypi/simple/ 阿里 https://pypi.hustunique.com/simple/ 华中理工大学 https://pypi.sdutlinux.org/simple/ 山东理工大学 https://pypi.mirrors.ustc.edu.cn/simple/ 中国科学技术大学 https://pypi.tuna.tsinghua.edu.cn/simple/ 清华
查看某一个依赖包安装的信息,执行命令:pip show 依赖包的名字:
pip show pytest
怎么把项目所需要的环境,传递给同事 -- 统一依赖包的版本(python的版本也要一样)
\# 示例:导出的文件名称可以自定义 pip freeze > request.txt
request.txt :自己定义的文件名
-
通过pycharm打开项目文件,然后创建一个虚拟环境
但凡是图标带V的,都是指代的虚拟环境,反之表示系统环境
2.拿到 request.txt 文件之后,执行命令,会按照request.txt 文件的要求,去下载依赖包的相关信息:
\# 建议加上国内的镜像源 pip install -r output.txt -i https://mirrors.aliyun.com/pypi/simple/
cmd执行方式
二.python的输入输出、数据类型
1.输入输出
#输出 print print("hello world") """ 注释 单引号和双引号没区别,但单引号和双引号要成对出现 """ ''' 注释 多行注释:鼠标选中要注释的内容,然后 ctrl + / 格式化代码:ctrl + alt + L (L=shift +l) 直接复制上一行代码:ctrl + D ''' #输入 input a=input("请输入密码") print(a) print("请输入您的密码:"+input()) """ 程序是有开始,有结束的---绝大数情况下 程序的运行规则:从上到下,由内而外----重点 """
2.格式化输出
""" 方式一: 使用%d、%f、%s 进行占位,后面的输出内容使用 %(value1, value2, value3) %d : 整数 %f:小数/浮点数 %s:字符串 """ print(""" =====自我介绍===== name: %s addr: %s age: %d sal: %f """ % ("七夜老师", "湖南长沙", 18, 1001)) """ 方式二: 直接使用 {} 进行占位,后面接 .format(value1, value2), 前面设置了几个占位符{},后面就需要传入几个值 """ print(""" =====自我介绍===== name: {} addr: {} age: {} sal: {} """.format("七夜老师", "湖南长沙", 18, 1001)) """ 方式三:在字符串引号前面加个f(只适用于变量) 然后字符串中间用{} 把变量的名称括起来 示例: """ name, age, sex = "七夜老师", 18, "man" print(f"名字:{name}") print(f"年龄:{age}") print(f"性别:{sex}") # 打印的结果 """ 名字:七夜老师 年龄:18 性别:man """
3.数字类型
常见的数字类型:
-
整数: 0-9组成的数字 int
-
浮点数:整数 + 小数点 + 小数 float
-
布尔值:对或者错 真(True)或者假(False),如果是做计算的话,True == 1,False == 0 bool
-
复数:实数 + 虚数,complex,比如:0.99j
type()用来获取数据的类型
示例:
print(type(9)) # <class 'int'> print(type(1 > 2)) # <class 'bool'> print(type(3 < 1)) # <class 'bool'> print(type(100 + 0.99j)) # <class 'complex'>
字符串类型
print("True") print(True)
带""的都属于字符串类型
4.变量的应用
定义:在计算机中,能够指代某个值或者结果的东西 -- 变量
用一个英文单词/字母,去代替某些值的时候,可以直接把这个单词/字母拿过来使用 -- 这个单词/字母称之为变量
举例:求圆的面积公式 S=π*r²,S为变量
num1=2 #在计算机中,=号,一个=号表示赋值,把最右边的值,赋值给左边的变量 num2=7 # ==号,两个便是判断是否等于的意思 # + - * / 对于python中的加减乘除
注意:python中,定义变量的时候,可以直接赋值,不需要提前去定义类型(区别:java语言)
多个变量赋值:
连续赋值:多个变量使用同一个值
a = b = 10 print(a) print(b) print(id(a))#输出a b的内存地址,值一样,地址相同 print(id(b))
多个变量使用多个值
name, age, sex = "七夜老师", 18, "man" print(name) print(age) print(sex)
一个变量赋多个值:* 号进行接收----* 号表示解包
a, b, *c = 1, 2, 3, 4, 5, 6, 7, 8, 9 print(f"a收到的值:{a}") print(f"b收到的值:{b}") print(f"c收到的值:{c}")
只能有一个* 号
5.类型转换
字符串--->整数 int("字符串(注意:数字类型)")
字符串--->浮点数 float()
字符串--->布尔值 boot()
字符串--->字符串 str()
示例一:
str1 = "100" a = int(str1) print("str1的数据类型:",type(a)) # <class 'int'>示例二:
# 错误的示例 str2 = "3.14" a = int(str2) print("str2的数据类型:",type(a)) # 正确的写法 str2 = "3.14" a = float(str2) b = int(a) print(b) print("str2的数据类型:",type(b)) #浮点类型字符串不能直接转换为int类型 不进行四舍五入
课后作业
1.输入两个数字,并且同时打印出来
2.请将字符串"3.1415926"转为浮点型并且乘以2,再转为整型进行输出
3.【项目】利用上课学过的知识完成以下需求实战:(利用format完成占位输出)
# 需求:
1)打印"欢迎来到xx同学的python书店" # 2)定义变量接收(book_name:"python",book_author:"七夜",book_num:10,book_price:77) # 3)最后格式化打印: # 同学你好,你需要购买的书籍名称为: {} ,价格为: {}元, # 作者为: {} , 当前库存数量为: {} 本,祝你学习愉快!~~
print("----欢迎来到ljl同学的python书店----") book_name = input("请输入书籍的名称:") book_author = input("请输入书籍的作者:") book_num = input("请输入书籍的库存数量:") book_price = input("请输入书籍的售卖价格:") print(""" 同学你好,你需要购买的书籍名称为: {} ,价格为: {}元, 作者为: {} , 当前库存数量为: {} 本,祝你学习愉快!~~ """.format(book_name, book_price, book_author, book_num))
三、python中的运算符、条件分支结构、循环结构
运算符
1.算数运算符
常见的运算符: 加(+) 减(-) 乘(*) 除( /)
print(num1 + num2) print(num1 - num2) print(num1 * num2) print(num1 / num2) # 问:运算的结果? 坑 15 5 50 2.0
注意:在做除法运算的时候,会出现一个小数点 -- 浮点数的类型
复杂的用法:
1)求余数: %
举个例子:现在有10个文件,分给3个人,请问余数为多少? -- 1
num1 = 10 num3 = 3 print("所得到的余数为: {}".format(num1 % num3)) # 运算的结果 所得到的余数为: 1
2)整除(只会取整数): //
num1 = 10 num3 = 3 print("整除后的结果为: {}".format(num1 // num3)) # 整除后的结果为: 3
3)幂(次方): **
num1 = 10 num3 = 3 print("次方得到的结果为: {}".format(num1 ** num3)) # 次方得到的结果为: 1000
特殊的用法:
举例:如果一半是数字,一半不是?
1)str类型 和 str类型:
两个str类型的值进行加法运算 -- 拼接(不要默认给英文单词之间,加上空格)
str1 = "hello" str2 = "world" print("两个str类型的值,进行加法计算的结果:{}".format(str1 + str2)) # 两个str类型的值,进行加法计算的结果:helloworld
2)str类型 和 数字类型:
多次打印str类型,打印的次数由数字类型决定
str1 = "hello" num4 = 3 print(str1+num4) #str和数字类型不能相加,可以相乘 print("str类型和数字类型,进行乘法运算:{}".format(str1 * num4)) # str类型和数字类型,进行乘法运算:hellohellohello
示例:
print("-" * 100) # ----------------------------------------------------------------------------------------------------
其他多种类型运算:
1)int类型 和 float类型:有可能存在一个问题 -- 精准度丢失(python的语言问题,不需要额外关注)
data = 3 f2 = 2.111 print("int类型 + float类型,得到的结果:{}".format(data + f2)) # int类型 + float类型,得到的结果:5.111000000000001
2)bool类型 和 int类型:
bool类型,在做计算的时候,True == 1, False == 0
bol = True # 直接定义的bool类型 data = 3 # 非0为true print("bool类型 + int类型,得到的结果:{}".format(bol + data)) # bool类型 + int类型,得到的结果:4
2. 比较运算符
包含:大于、小于、等于、不等于、大于等于、小于等于
返回的结果:bool值,True、False
等于: ==
不等于:!=(英文格式)
大于等于:>=
小于等于:<=
a = 10 b = 5 print(f"大于:{a > b}") print(f"小于:{a < b}") print(f"等于:{a == b}") # 两个=号,表示判断是否相等 print(f"不等于:{a != b}") # != 表示不等于 print(f"大于等于:{a >= b}") print(f"小于等于:{a <= b}") # 结果: 大于:True 小于:False 等于:False 不等于:True 大于等于:True 小于等于:False
3.赋值运算符
单个的=号,表示赋值的意思
赋值:把=号,右边的值,赋值给左边
a = 10 a += 5 # 属于简写:a = a + 5 的结果 print(f"a += 5 的结果:{a}") # 结果:a += 5 的结果:15 a -= 5 a *= 5 a /= 5
注意事项:程序的执行顺序(从上到下,由内而外)
a = 10 a += 5 a *= 5 print(f"a += 5 的结果:{a}") # a += 5 的结果:75
4.逻辑运算符
返回的结果:bool值,True、False
包括:与(and) 或(or) 非(not)
定义:
与运算:所有逻辑都是True,最终结果才是True -- 同真为真,有假为假
或运算:只要有一个逻辑是True最终结果就是True -- 同假为假,有真为真
非运算:不管别人是正确还是错,他一定要反对 -- 杠精,相对
示例:
a = True b = False print(f"与运算:{a and b}") # False print(f"或运算:{a or b}") # True print(f"非运算:{not b}") # True
练习:
1)优先级:比较 > 逻辑
print(1 > 2 and 4 > 3) # False # False and True # False print(1 > 2 or 4 > 3) # True # False or True # True
答:True and False,与运算:所有逻辑都是True,最终结果才是True -- 同真为真,有假为假
2)优先级:not > and > or
print(True and False or True and not False) # True # True and False or True and True # False or True # True
3)优先级:算数 > 比较 > 逻辑(not > and > or)
print(1 + 1 > 1 + 2 and 3 + 2 < 3 - 1 or 5 and not True) # False # 2 > 3 and 5 < 2 or 5 and not True # False and False or 5 and not True # False and False or 5 and False # False or False # False
提问:5 and False,这个地方的值为多少?
答:False
False or 5 输出结果为 :5
-
与运算:所有逻辑都是True,最终结果才是True -- 同真为真,有假为假
-
做判断的时候:非0则为True
5.成员运算符
定义:判断指定内容是否包含在某个内容中 包含关系
返回的结果:bool值,True、False
in:存在(包含)
not in:不存在(不包含)
示例:
str1 = "qiyelaoshi" print("判断'qiye'是否存在str1变量里面:{}".format('qiye' in str1)) # True print("判断'qiye'是否存在str1变量里面:{}".format('qiye' not in str1)) # False
注意:
1)bool类型的数据,是不能够做成员运算符的计算:
bol = True print("'T'是否存在bol变量里面:".format('T' in bol)) # 报错信息:argument of type 'bool' is not iterable
2)数字类型的数据,是不能够做成员运算符的计算:
num1 = 123 #数字是一个整体,无法去判断包含还是不包含 print(1 in num1) # 报错信息:argument of type 'int' is not iterable
条件分支结构
1.单向分支
语法结构:
if 判断条件(运算符、bool值): 逻辑代码(1. 如果条件满足 -- True,就执行这部分逻辑代码; 2. 如果不满足,就跳过这段逻辑代码,不执行)
示例:如果用户输入了'admin'的内容,那么输出'欢迎管理员登录'
name = input("提示用语[请输入您的登录账号]: ") # 用变量接收输入的值 if name == 'admin': # 判断的条件:拿[输入的内容]和[预期结果]作是否相等的判断 print("欢迎管理员登录")
2.双向分支
如果条件不满足,那么就执行另一块代码,这两块代码一定不会同时执行
语法结构:
if 判断条件(运算符、bool值): 逻辑代码(1. 如果条件满足 -- True,就执行这部分逻辑代码; 2. 如果不满足,就跳过这段逻辑代码,不执行) else: 逻辑代码(if条件不满足的情况下,才会执行else,如果满足if条件,则跳过else代码块,不执行)
示例:排除特殊性的场景,如果你不是一个男孩子,那么一定是一个女孩子
sex = input("请问您是男孩子么?请输入:yes 或 no:") if sex == 'yes': print("那你应该喜欢打篮球") else: print("那你应该喜欢口红")
3.多向分支
存在多个条件判断,只要满足一个条件,就不会去执行其他条件
语法结构:
if 判断条件1(运算符、bool值): #逻辑代码1(1. 如果条件满足 -- True,就执行这部分逻辑代码; 2. 如果不满足,就跳过这段逻辑代码,不执行) elif 判断条件2: #逻辑代码2(1. 如果条件满足 -- True,就执行这部分逻辑代码; 2. 如果不满足,就跳过这段逻辑代码,不执行) elif 判断条件3: #逻辑代码3(1. 如果条件满足 -- True,就执行这部分逻辑代码; 2. 如果不满足,就跳过这段逻辑代码,不执行) ... ... else: #逻辑代码(如果以上条件都不满足,才会执行else,如果满足以上的任意条件,则跳过else代码块,不执行)
示例:买票的条件
\1. 60以上,3以下 [免票]
\2. 12 - 59 成人票[全票]
\3. 4 - 11 儿童票[半票]
age = int(input("请输入您的年龄:")) # int(需要转换的数据) if age >= 60 or age <= 3: # [免票]的区间 print("[免票]") elif age >= 12 and age < 60: # 成人票[全票]的区间 print("成人票[全票]") elif age >= 4 and age < 12: # 儿童票[半票] print("儿童票[半票]")
注意:input()方法接收的值,都是str类型
4.if判断条件
理论上说 if 后面可以接任意条件,只要它的结果是bool值就行
使用的情况:
-
比较: > < ==
-
逻辑: and or not
-
成员:in not in
-
数学: + - * /
-
直接使用bool值
示例:
\# 1) if 1 - 1: # 1 - 1 = 0,非0则为True,0则为False print("if打印的内容") else: print("else打印的内容") # 2) b = input("请输入文字:") if 'qiye' in b: print("if打印的内容") else: print("else打印的内容") # 3) a = int(input("请输入数字:")) if a - 1: # 1 - 1 = 0 print("if打印的内容") else: print("else打印的内容")
5.子分支
if的嵌套,if ... else ...里面再去嵌套 if ... else ...
if 条件1: 代码块1 if 条件2: 代码块2 else: 代码块b else: 代码块b #if和else可以无限嵌套
示例:相亲的条件,条件1:满足180身高;条件2:满足月薪100;
hight = int(input("请输入相亲对象的身高:")) if hight >= 180: print("可以考虑一下") sal = int(input("请输入相亲对象的工资:")) if sal >= 100: print("可以见一面") else: print("我还是考虑考虑吧") else: print("不好意思,不考虑,我要加班")
循环结构_while
1.while循环
让某段代码逻辑去反复执行,这个就叫循环,具体的执行次数,就是由条件决定的
语法结构:
while 判断条件: 逻辑代码
-
只要判断条件为True这个代码块就会反复执行,执行到代码的最后一行重新判断条件,
-
如果判断条件还是True就继续执行一次,如此反复
-
如果判断条件是False,就跳出循环
-
while是关键字(python固定设置的内容)
-
如果while的判断条件,始终满足----一直执行/死循环-----避免---改变while的条件
示例:
while True: print("欢迎来到七夜老师的课堂!")
注意:当while的判断条件始终为True的时候,会进入死循环
不要让while的循环条件恒定,需要有办法改变它原来的条件
方式一:引用变量,让条件不会恒定,让变量可以变化,同时与while条件相结合
a = 0 # 设置一个初始值 while a < 6: # a的取值:0、1、2、3、4、5 print("欢迎来到七夜老师的课堂!") a += 1 # a每循环一次,就会在原有的基础上进行 +1 # 提问:会打印几次?6次
2.关键字避免死循环
break :直接终止整个循环,不去判断条件,直接结束循环
continue:遇到continue这个关键字,这个时候不去执行循环内部往下的代码(循环内部),直接重新去判断条件
区别:
continue:中断当前循环,直接执行判断条件。如果条件为True,继续执行,如果条件为False,就停止循环
break:直接中断整个循环,不去判断条件,直接循环结束
示例:
a = 10 # 设置的初始值 while a: # a的取值为:9、8、7、6、5、4 a -= 1 if a % 2 == 0: print(f"当前的值为偶数,此时a的值为:{a}") continue # 中断当前循环,直接执行判断条件 if a < 5: print(f"当a的值小于5了,直接结束循环,此时a的值为:{a}") break # 中断整个循环,直接结束 # 提问:当a的值为多少的时候,跳出循环?3 # 同学们的问题:为什么不是4的时候,跳出循环? # 程序的运行顺序,从上往下,a=4时会先满足第一个if判断的时候,直接continue,重新判断条件,然后重新回到a-=1去执行,然后a=3,不满足第一个if条件不执行,就到了第二个if中执行,然后就遇到了break终止循环
课后作业
""" 1.定义两个变量num_1、num_2接收两个浮点型的数字字符串,然后进行转换,并且分别打印出加减乘除的计算结果 (涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位) 2.定义两个变量num_1、num_2接收两个浮点型的数字字符串,进行类型转换,然后再定义一个变量operation_symbol接收一个加减乘除的字符串,并通过if判断对两个数字进行运算和结果输出 (涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位) 3.结合以上条件,引用while循环,让其可以循环输入运算符号和计算结果,添加输入错误提示:"输入有误,无法识别,请重新操作",输入"exit"退出系统功能(while、continue、break) 4.一家商场在降价促销,如果购买金额50-100元(包含50和100元)之间,会给10%的折扣,如果购买金额大于100元会给20%的折扣, 编写一个程序,询问购买价格,再显示出折扣,(10%或20%,可以直接乘以0.1或者0.2)和最终价格 5.输入一个年份,输出是否为闰年。 闰年条件:能被4整除但不能被100整除,或者能被400整除但年份都是闰年 6.完成一个猜数字游戏 # 进入程序后 # 提示用户输入 要猜的数字 # 其他人输入时,提示数字大了,或者小了 # 猜到正确的""" 1.定义两个变量num_1、num_2接收两个浮点型的数字字符串,然后进行转换,并且分别打印出加减乘除的计算结果 (涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位) 2.定义两个变量num_1、num_2接收两个浮点型的数字字符串,进行类型转换,然后再定义一个变量operation_symbol接收一个加减乘除的字符串,并通过if判断对两个数字进行运算和结果输出 (涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位) 3.结合以上条件,引用while循环,让其可以循环输入运算符号和计算结果,添加输入错误提示:"输入有误,无法识别,请重新操作",输入"exit"退出系统功能(while、continue、break) 4.一家商场在降价促销,如果购买金额50-100元(包含50和100元)之间,会给10%的折扣,如果购买金额大于100元会给200%的折扣, 编写一个程序,询问购买价格,再显示出折扣,(10%或20%,可以直接乘以0.1或者0.2)和最终价格 5.输入一个年份,输出是否为闰年。 闰年条件:能被4整除但不能被100整除,或者能被400整除但年份都是闰年 6.完成一个猜数字游戏 # 进入程序后 # 提示用户输入 要猜的数字 # 其他人输入时,提示数字大了,或者小了 # 猜到正确的数字为止,提示恭喜猜对了 # (选做:可以控制每位玩家的猜数字次数,例如,一个人只能猜3次,3次猜错结束程序,显示正确的数字后,重新开始) # (选做: 猜数字的游戏中的数字尝试让系统生成,提示:random.randint(n,m) 可以让python在n-m之间生成一个随机数) # 7.【项目】结合今天所学的内容,对上节课的作业项目进行升级 # 模拟课堂上的project_duck,改编自己的书籍项目(包含while、break、if等知识点) """ # 1.定义两个变量num_1、num_2接收两个浮点型的数字字符串,然后进行转换,并且分别打印出加减乘除的计算结果 # (涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位) # num_1 = float(input("请输入第一个数字:")) # num_2 = float(input("请输入第二个数字:")) # print("加法计算的结果为: {}".format(num_1 + num_2)) # print("减法计算的结果为: {}".format(num_1 - num_2)) # print("乘法计算的结果为: {}".format(num_1 * num_2)) # # print("除法计算的结果为: {}".format(num_1 / num_2)) # print("除法计算的结果为: {}".format(round((num_1 / num_2), 2))) # 2.定义两个变量num_1、num_2接收两个浮点型的数字字符串,进行类型转换,然后再定义一个变量operation_symbol接收一个加减乘除的字符串, # 并通过if判断对两个数字进行运算和结果输出 # (涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位) # num_1 = float(input("请输入第一个数字:")) # num_2 = float(input("请输入第二个数字:")) # operation_symbol = input("请输入(+、-、*、/)中的运算符号:") # # if operation_symbol == "+": # print(num_1 + num_2) # elif operation_symbol == "-": # print(num_1 - num_2) # elif operation_symbol == "*": # print(num_1 * num_2) # elif operation_symbol == "/": # print(round((num_1 / num_2), 2)) # 3.结合以上条件,引用while循环,让其可以循环输入运算符号和计算结果,添加输入错误提示:"输入有误,无法识别,请重新操作", # 输入"exit"退出系统功能(while、continue、break) # num_1 = float(input("请输入第一个数字:")) # num_2 = float(input("请输入第二个数字:")) # # while True: # operation_symbol = input("请输入(+、-、*、/)中的运算符号:") # if operation_symbol == "+": # print(num_1 + num_2) # elif operation_symbol == "-": # print(num_1 - num_2) # elif operation_symbol == "*": # print(num_1 * num_2) # elif operation_symbol == "/": # print(round((num_1 / num_2), 2)) # elif operation_symbol == "exit": # print("退出系统") # break # else: # print("输入有误,无法识别,请重新操作") # continue # 4.一家商场在降价促销,如果购买金额50-100元(包含50和100元)之间,会给10%的折扣,如果购买金额大于100元会给20%的折扣, # 编写一个程序,询问购买价格,再显示出折扣,(10%或20%,可以直接乘以0.1或者0.2)和最终价格 # amount = float(input("请输入购买的金额: ")) # if 50 <= amount <= 100: # print("您当前购买的金额享受10%的折扣,折算完的金额为: {}元".format(amount - amount * 0.1)) # elif amount > 100: # print("您当前购买的金额享受20%的折扣,折算完的金额为: {}元".format(amount - amount * 0.2)) # 5.输入一个年份,输出是否为闰年。 # 闰年条件:能被4整除但不能被100整除,或者能被400整除但年份都是闰年 # year_num = int(input("请输入年份:")) # if year_num % 4 == 0 and year_num % 100 != 0 or year_num % 400 == 0: # print("您输入的年份是闰年!") # else: # print("您输入的年份不是闰年!") # 6.完成一个猜数字游戏 # 进入程序后 # 提示用户输入 要猜的数字 # 其他人输入时,提示数字大了,或者小了 # 猜到正确的数字为止,提示恭喜猜对了 # (选做1:可以控制每位玩家的猜数字次数,例如,一个人只能猜3次,3次猜错结束程序,显示正确的数字后,重新开始) # (选做2: 猜数字的游戏中的数字尝试让系统生成,提示:random.randint(n,m) 可以让python在n-m之间生成一个随机数) # be_guess_num = float(input("请输入要猜的数字为: ")) # # while True: # guess_num = float(input("请输入猜测的数字为: ")) # if guess_num > be_guess_num: # print("数字太大!") # elif guess_num < be_guess_num: # print("数字太小!") # else: # print("恭喜你,猜对了!") # break # (选做1:可以控制每位玩家的猜数字次数,例如,一个人只能猜3次,3次猜错结束程序,显示正确的数字后,重新开始) # be_guess_num = float(input("请输入要猜的数字为: ")) # num = 0 # # while num < 4: # num += 1 # guess_num = float(input("请输入猜测的数字为: ")) # if guess_num > be_guess_num: # print("数字太大!") # elif guess_num < be_guess_num: # print("数字太小!") # else: # print("恭喜你,猜对了!") # break # # if num == 3: # print("次数已用尽,正确的数字为: {},游戏重新开始".format(be_guess_num)) # num = 0 # continue # (选做2: 猜数字的游戏中的数字尝试让系统生成,提示:random.randint(n,m) 可以让python在n-m之间生成一个随机数) # import random # # be_guess_num = random.randint(1, 100) # num = 0 # # while num < 4: # num += 1 # guess_num = float(input("请输入猜测的数字为: ")) # if guess_num > be_guess_num: # print("数字太大!") # elif guess_num < be_guess_num: # print("数字太小!") # else: # print("恭喜你,猜对了!") # break # # if num == 3: # print("次数已用尽,正确的数字为: {},游戏重新开始".format(be_guess_num)) # num = 0 # continue # 7.【项目】结合今天所学的内容,对上节课的作业项目进行升级 # 模拟课堂上的project_duck,改编自己的书籍项目(包含while、break、if等知识点) print("欢迎来到七夜老师的python书店") book_name = None book_author = None book_num = None book_price = None print(book_price, book_author, book_num, book_name) while True: input_txt = input("请输入您要选择的操作\n1 - 录入书籍\n2 - 查询书籍\n3 - 退出") if input_txt == "1": book_name = input("请输入书籍的名称:") book_author = input("请输入书籍的作者:") book_num = input("请输入书籍的库存数量:") book_price = input("请输入书籍的售卖价格:") elif input_txt == "2": print("书籍的名称: {}".format(book_name)) print("书籍的作者: {}".format(book_author)) print("书籍的库存数量: {}".format(book_num)) print("书籍的售卖价格: {}".format(book_price)) elif input_txt == "exit": print("退出系统!") break 数字为止,提示恭喜猜对了 # (选做:可以控制每位玩家的猜数字次数,例如,一个人只能猜3次,3次猜错结束程序,显示正确的数字后,重新开始) # (选做: 猜数字的游戏中的数字尝试让系统生成,提示:random.randint(n,m) 可以让python在n-m之间生成一个随机数) # 7.【项目】结合今天所学的内容,对上节课的作业项目进行升级 # 模拟课堂上的project_duck,改编自己的书籍项目(包含while、break、if等知识点) """
四、列表和字典的定义与操作
Python可视化网址:Python Tutor code visualizer: Visualize code in Python, JavaScript, C, C++, and Java
Project_Duck(烤鸭店例子):
需求:
烤鸭店利润计算器:计算这个烤鸭店每天的利润是多少?
要求:
a)要求提示页面友好
b)要求自己可以手动输入收入、成本、鸭子数量
(1)收入 - 成本 = 利润
# 第一个版本: print("欢迎使用烤鸭店利润计算器!") price1 = input("请输入今天的收入金额为: ") # 1000 price2 = input("请输入今天的成本金额为: ") # 600 result = price1 - price2 # 问题:这种方式可行么?不行,input函数所接受的值是str类型 # 报错信息:unsupported operand type(s) for -: 'str' and 'str'
优化后的代码:
# 优化后的代码: print("欢迎使用烤鸭店利润计算器!") price1 = int(input("请输入今天的收入金额为: ")) # 1000 price2 = int(input("请输入今天的成本金额为: ")) # 600 result = price1 - price2 print(f"今天的纯收入是:{result}")
(2)(单个鸭子的售卖价格 - 成本价格) * 今天售卖的鸭子数量 = 今天烤鸭店的利润
print("欢迎使用烤鸭店利润计算器!") price1 = int(input("请输入今天的收入金额为: ")) # 1000 price2 = int(input("请输入今天的成本金额为: ")) # 600 duck_num = int(input("请输入今天售卖的鸭子数量为: ")) result = (price1 - price2) * duck_num print(f"今天的收入金额为: {price1}, 成本金额为: {price2}, 纯收入是:{result}")
(3)由于烤鸭店的利润太少了,想要新增一些商品类型[属性:商品的名称、价格、生产日期、生产地、保质期 ... ...]
错误示例:
p1 = "北京烤鸭" m1 = 80 p2 = "北京卷饼" m2 = 5 # ... ... 要新增很多的商品,那么这种写法可行么?一种商品可能存在5条属性,那么如果有100种商品,是不是存在100 * 5 = 500行代码? # 原因:维护性特别差,一般不这么做 -- 开发一时爽,维护火葬场
1.列表
列表的定义:
定义:一种将多个数据组合在一起的容器
标识符:[ ]
关键字:list
定义一个空列表
lst1 = []
定义一个有值的列表,每个元素之间用英文的逗号隔开
lst2 = [1, 2, 3, 4]
获取列表的类型:
lst2 = [1, 2, 3, 4] # 定义一个有值的列表,每个元素之间用英文的逗号隔开 print(type(lst2)) # <class 'list'>
列表的增删改查操作:
特征:有序、可变
有序:列表中的每个元素都是有索引(python中的索引,都是默认从 0 开始)
列表的取值语法:列表的变量名称[索引的值]
lst1 = [1, 2, 3, 4, 5] print(lst1[3]) # 4
获取列表的长度 -- len()
lst1 = [1, 2, 3, 4, 5] # 有几个元素,那么len长度就是多少 print(len(lst1))
列表可以倒叙输出 -- reverse()
lst1.reverse() # 先执行方法完成倒叙 print(lst1) # 然后再去查询 #错误写法 print(lst1.reverse()) #一边打印,一边倒叙的话,会打印为None(表示的是这个函数没有返回值)这个None在后面的函数会讲
小测验:
lst3 = [100, 3.14, True, "qiyelaoshi", [1, 2, 3, 4]] # 问题1:获取 "qiyelaoshi" 这个值 print(lst3[3]) # 问题2:请问lst3的len长度为多少? print(len(lst3)) # 问题3:获取 3 这个值? print(lst3[4]) # 这个元素还是list类型的值 #想要获取到嵌套的数据,先找到最外面的一层 print(lst3[4][2]) # 把lst3[4]视为一个整体的list,然后使用list取值的方式进行操作 # 问题4:lst3的长度为? lst3 = [100, 3.14, True, "qiyelaoshi", [1, 2, 3, 4], [1, 2, 3, 4, [1, 2, 3, 4], [1, 2, 3, 4]]] # 快捷的查看方式:数括号,括号是一一对应的,从最外层开始数 print(len(lst3)) #6
列表的增加 -- append()
会把添加的值,默认加在末尾,一次只能添加一个元素
lst1 = [1, 2] lst1.append("qiyelaoshi") print(lst1) # 错误示例: lst1.append("qiyelaoshi", "xiaominglaoshi") # list.append() takes exactly one argument (2 given)
列表的添加 -- insert()
通过索引来进行添加,添加的位置就是索引的位置,原有位置元素下标会依次加一?
lst1 = [1, 2] #按照下标完成添加,插入数据前面的下标不管,后面的数据下标依次递增+1 lst1.insert(0, "qiyelaoshi") print(lst1)
合并列表 -- extend()
把元素一个个的放入到新的列表中
lst1 = [1, 2] lst2 = [2, 3, 4, 5] # print(lst1 + lst2) # 不建议在企业中,写法太低级,看起来像是加法运算 lst1.extend(lst2) print(lst1) # 把str类型的数据,合并到列表中 lst1.extend("七夜老师") # str类型也是可以视为列表 print(lst1) # [1, 2, '七', '夜', '老', '师'] #错误示例,数字类型不可迭代 lst1.extend(100) print(lst1)
列表的删除 -- remove()
直接删除具体的值,如果存在多个的话,默认删除最前的那个
lst1 = [1, 2] lst2 = [2, 3, 4, 5, 2] lst1.remove(2) print(lst1) # 问题:通过remove删除lst2中的值2 ,那么会删除前面的还是后面的 lst2.remove(2) print(lst2)
列表的删除 -- pop()
不带下标,默认删除最后一个,带下标删除具体的值
lst1 = [1, 2] lst2 = [2, 3, 4, 5, 2] # lst1.pop() # print(lst1) lst2.pop(3) print(lst2)
列表的删除--del
请删除列表中的第2至第4个元素 del li[1:4]
列表的修改
-- 列表的变量名称[下标] = 新值
lst3 = [100, 3.14, True, "qiyelaoshi", [1, 2, 3, 4]] # 问题1:把 True 改为False? # lst3[2] = False # print(lst3) # [100, 3.14, False, 'qiyelaoshi', [1, 2, 3, 4]] # 问题2:把 3 改为 10 ? lst3[4][2] = 10 print(lst3) # [100, 3.14, True, 'qiyelaoshi', [1, 2, 10, 4]]
烤鸭店项目的升级:
project_duck_3.0
print("欢迎使用烤鸭店利润计算器!") price1 = int(input("请输入今天的收入金额为: ")) # 1000 price2 = int(input("请输入今天的成本金额为: ")) # 600 duck_num = int(input("请输入今天售卖的鸭子数量为: ")) result = (price1 - price2) * duck_num print(f"今天的收入金额为: {price1}, 成本金额为: {price2}, 纯收入是:{result}")
通过列表对烤鸭店进行升级,提高代码的可维护性
project_duck_3.1
print("欢迎使用七夜老师的烤鸭店利润计算器!") projects = {} #定义一个最外层的的数据,用于保存 while True: # 让系统可以循环使用,不用每次都手动执行 # 提供一个可选择功能的菜单 #转义字符,键盘上有部分的键,不能在代码中显示 #\n表示换行的意思 #如果说不希望字符串自动转义---在引号的前面加一个r,比如r"请输入对应的数字进行功能选择:\n1.录入商品的功能\n2.查询商品的功能\n3.退出系统的功能\n" oper_type = input("请输入对应的数字进行功能选择:\n1.录入商品的功能\n2.查询商品的功能\n3.退出系统的功能\n") if oper_type == "1": # 1.录入商品的功能 pro_list = [] # 定义一个空列表 load_name = input("请输入你的商品名:") pro_list.append(load_name) price = input("请输入你的成本价:") pro_list.append(price) s_value = input("请输入你的产地:") pro_list.append(s_value) data_time = input("请输入你的生产日期:") pro_list.append(data_time) # 问题:怎么把pro_list的值,加到projects里面去? projects[load_name]=pro_list elif oper_type == "2": # 2.查询商品的功能 print(projects) po_name=input("请输入你要查询的商品名称:") print(f"您要查询的商品信息:{projects[po_name]}") elif oper_type == "3": # 3.退出系统的功能 break # 直接跳出整个循环 else: print("系统无法识别你的输入,请重新选择!") continue # 跳出当前循环,重新判断条件
2. 字典
字典的定义:
定义:具有键值对映射关系的一组无序的数据组合
键值对映射: key : value -- key是键名,value是这个键所对应的具体值,通过key来查询
关键字:dict
标识符:{}
无序:没有索引 一个字典里的key不会重复
key:是唯一的,并且不能修改的数据,通常我们用str类型
value: 可以是任何类型的数据,可以修改
定义一个空字典
dic1 = {}
定义一个有值的字典
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] }
字典的查询 -- 字典的变量名称["key"]`
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] } print(dic2["students_name"]) # ['二师兄', '千寻', '听风、', '自由']
小测验:
问题:查询 听风、这个值?
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] } print(dic2["students_name"][2]) # 听风、
字典的增删改操作:
字典的新增
字典的变量名称["字典中不存在的key"] = 新值---向字典中添加一组键值对
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] } dic2['addr'] = "湖南长沙" print(dic2) # {'name': '七夜老师', 'age': 18, 'cls': 234, 'students_name': ['二师兄', '千寻', '听风、', '自由'], 'addr': '湖南长沙'}
字典的修改
-- 字典的变量名称["字典中存在的key"] = 新值---把原有字典的value换成新的
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] } dic2['age'] = 20 print(dic2)
提问:把 自由 的值,改为 小玉 ?
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] } dic2["students_name"][3] = "小玉" print(dic2)
字典的删除 -- pop()
不能为空,需要传入删除的key
错误的示例:
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] } dic2.pop() # pop expected at least 1 argument, got 0
正确的示例:
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] } dic2.pop("age") print(dic2) # {'name': '七夜老师', 'cls': 234, 'students_name': ['二师兄', '千寻', '听风、', '自由']}
字典的删除 -- popitem()
从后往前删出
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] } dic2.popitem() print(dic2) # {'name': '七夜老师', 'age': 18, 'cls': 234}
问题:当dict中所有的key都被删除了,还剩下什么?
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] } dic2.popitem() dic2.popitem() dic2.popitem() dic2.popitem() print(dic2) # {}
字典的清空 -- clear()
dic2 = { "name": "七夜老师", "age": 18, "cls": 234, "students_name": ["二师兄", "千寻", "听风、", "自由"] } dic2.clear() print(dic2) # {}
转义字符:键盘上有部分键,不能在代码里显示, 用英文去代替特殊键位
五、for循环和切片
循环
特征:遍历、循环
遍历:复杂的数据结构中,将里面的元素一个个的获取出来
循环:自带循环的效果,循环的次数由可遍历数据的长度来决定
语言结构:
for 变量名 in 可遍历的数据: # 变量名:自定义的变量名(可以获取到每次循环的元素); 可遍历的数据包含:列表、字符串... ... 循环体的代码:每循环一次,执行一遍循环代码
通过for循环直接读取
lst1 = [1, "七夜老老师", 3, "a", "b", 6] for i in lst1: print(i)
小测验:
# 此时,打印的i的值为多少? j = 0 # 初始值 for i in lst1: if j % 2 == 0: # j取值的范围为多少:0,2,4 print(i) j += 1 # j每次循环都递增1 # 答案:1, 3, "b"
迭代器:range() 用于生成一个整数的序列,提供一个数字,自动生成一个序列列表(规则:左闭右开) -- 可迭代的对象
r = range(10) print(list(r)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] r1 = range(8) print(list(r1)) # [0, 1, 2, 3, 4, 5, 6, 7]
range()可以设置初始值,如过不设置,默认为0,如果设置了,只能够取到初始值到结束值之间的内容 -- 左闭右开
示例:
r2 = range(1, 10) print(list(r2)) # [1-9] r3 = range(8, 9) print(list(r3)) # [8]
range()结合for循环进行使用:
for i in range(10): # [0-9] print(i)
小测验:
# 问题1:for循环不能够遍历非可迭代的数据,比如:int类型 # for i in 10: # 'int' object is not iterable # print(i) # 问题2:for循环可以遍历str类型?str类型是可以当做列表 for i in "七夜老师": print(i) # 问题3:如果range()的开始值和结束值为同一个的话,能否取到值? r4 = range(8, 8) print(list(r4)) # [] 无法同时满足两个条件,则取不到值
双重for循环
for循环的嵌套
示例:
# k = 0 # 初始值 # # for i in range(1, 10): # [1-9] # # for j in range(1, 10): # k += 1 # 每循环一次,k都会递增1 # # print(f"k此时的值为:{k}") # 当第一层for循环,循环1次的时候,里面这个for循环,循环几次? # i每循环1次,都会让j循环9次,i最终会循环9次,就会导致双重for循环的最终循环次数:9 * 9 = 81
小测验:
笔试题:打印九九乘法表 1 * 1 = 1 1 * 2 = 2, 2 * 2 = 4 1 * 3 = 3, 2 * 3 = 6, 3 * 3 = 9 ... 1 * 9 = 9, 2 * 9 = 18, 3 * 9 = 27 ...
正确的写法和思路:
# print("{} * {} = {}".format(1, 2, 1 * 2)) # 定义了两个变量,一个是i,一个是j,总共的循环次数为81次 for i in range(1, 10): # [1-9] for j in range(1, i+1): # [1 - 9] print("{} * {} = {}".format(j, i, i * j), end=' ') # 防止换行 # 问题:当循环到第几次的时候,要求换行? print() # 这个print放在哪个循环里面?j?i? -- i # 当 i = 1 , 此时 j = [1-9],j循环打印的时候,有没有换行? -- j是不进行换行 # 核心点1: # 谁负责纵向的循环,谁负责横向的循环? # j:横向,i:纵向 # 核心点2: # 出现了多余的数据,应该修改谁的取值范围? -- j # i = 1, j循环9次,实际的需求:1次 # i = 2,j循环9次,实际的需求:2次 # i = 3,j循环9次,实际的需求:3次 # i = 4,j循环9次,实际的需求:4次 # i = 5,j循环9次,实际的需求:5次 # i = 6,j循环9次,实际的需求:6次 # 核心点3: # 怎么修改j的取值 # i和j的初始取值都是一样的,那么j的取值范围range()的开始值不改变 # i = 1 的时候,j的取值range(1, 2)才可以取到值1 # i = 2 的时候,j的取值range(1, 3)才可以取到值1, 2 # i每次递增,那么j的range(1, i+1)
查看源码**:Ctrl + 鼠标左键 点击你要查看的函数/方法内容**
print的源码:
因为print里面有\n,那么就表示print方法执行的时候,会自动换行
切片操作
列表的切片
列表的切片:分割一个列表,只提取其中某一个片段出来
语法规则:列表的变量名称[start:end:step]
start:开始值,从哪个地方开始
end:结束值,从哪里结束
step:步长,每隔几个元素获取一次值,默认值:1,可以省略,但是不能为0,否则就会报错
示例:
lst1 = [100, 3.14, True, "Huace", [1, 2, 3, 4]] # 根据下标取值 # print(lst1[1]) # 切片取值: # print(lst1[0:2]) # start:end,[100, 3.14] # print(lst1[1:2]) # 结果:[3.14] # print(lst1[1:4]) # [3.14, True, 'Huace'] # 问题:获取 True, "Huace" 的值,怎么写? # print(lst1[2:4]) # print(lst1[0:-1]) # 行不行?可以,[100, 3.14, True, 'Huace'] # print(lst1[:3]) # start 省略 # print(lst1[1:]) # end 省略 # print(lst1[0::2]) # 每隔几个元素,取一次值 print(lst1[0::0]) # slice step cannot be zero
切片的赋值方式,切记不要变量直接赋值变量
lst2 = [1, 2, 3, 4] lst3 = lst2 # 变量赋值变量的操作 # print(lst3) # print(lst2) # 隐患问题存在,如果给lst3中添加一个元素,那么lst2的元素是否会发生变化? -- 相等,安全性问题 lst3.append(5) print(lst3) print(lst2)
统计数据中元素的个数,count(元素具体值) -- 判断这个元素在我们列表中有几个
一个萝卜一个坑,判断的是最外面的数据中,有几个目标元素
lst1 = [100, 3.14, True, "Huace", [1, 2, 3, 4, True, True], [True, True]] print(lst1.count(True))
字符串的切片
str类型可以当做列表
语法规则:列表的变量名称[start:end:step]
start:开始值,从哪个地方开始
end:结束值,从哪里结束
step:步长,每隔几个元素获取一次值,默认值:1,可以省略,但是不能为0,否则就会报错
示例:
str1 = "hello python" # res = str1[0] # print(res) # res1 = str1[5] # 空格也是一个元素 # print(res1) # 负数取值,倒过来取值,取第几个 # res2 = str1[-1] # print(res2) # for i in str1: # print(i) # str类型的切片 # res3 = str1[0:3:2] # print(res3)
Project_Duck(烤鸭店项目)
project_duck_4.1:
print("欢迎使用七夜老师的烤鸭店利润计算器!") projects = {} while True: # 让系统可以循环使用,不用每次都手动执行 # 提供一个可选择功能的菜单 oper_type = input("请输入对应的数字进行功能选择:\n1.录入商品的功能\n2.查询商品的功能\n3.退出系统的功能\n") if oper_type == "1": # 1.录入商品的功能 pro_list = [] # 定义一个空列表 # 1) 把input里面的str数据,放在一个列表中 load_txt = ['请输入你的商品名:', "请输入你的成本价:", "请输入你的产地:", "请输入你的生产日期:", "请输入商品的属性a: ", "请输入商品的属性b: "] # 2) 把列表中的str数据,通过for循环,依次放在input中 # for i in load_txt: # input(i) # 3) 在通过变量的重定义,重新赋值定义一个变量,用来接收input每次循环时所接收的值 # for i in load_txt: # load_name = input(i) # 4) 把接收的值,依次添加到pro_list列表中 for i in load_txt: load_name = input(i) pro_list.append(load_name) # 问题:怎么把pro_list的值,加到projects里面去? # projects.append(pro_list) projects[pro_list[0]] = pro_list # key的值应该用哪个?给商品名称,value给整个商品的属性列表 elif oper_type == "2": # 2.查询商品的功能 # 如果想自己输入查询的商品名称进行查询 -- 根据key的名字查询对应的value print(projects) # 用户自己输入查询的商品名称 po_name = input("请输入您要查询的商品名称:") print(f"您查询到的商品信息为: {projects[po_name]}") elif oper_type == "3": # 3.退出系统的功能 break # 直接跳出整个循环 else: print("系统无法识别你的输入,请重新选择!") continue # 跳出当前循环,重新判断条件
回退缩进:shift + tab
六、 元组、集合和函数的定义与返回值
元祖
元组的定义
元组的数据结构跟列表相似
特征:有序、不可变
-
有序:有(索引/下标/index) 正序、反序
-
标识符: ( ) 里面的元素是用英文格式的逗号分割开来
-
关键字:tuple
面试中常问的问题:列表和元组有什么区别?
元组是不可变的:程序在运行的时候,无法对其进行改变 -- 没有提供关键字、方法去操作它,没有增删改的操作
问题:既然无法对其进行变化,那么为什么要有元组的存在?
安全性考虑 -- 国内的省份(省、市) 变量,常量
但凡是可以进行操作的数据,都存在安全隐患
示例:
tp = () # 定义一个空元组 print(type(tp)) # <class 'tuple'> tp1 = (1, 2, 3, 4, 5) # 定义一个有值的元组 print(tp1)
元组的基本查询,根据下标
tp1 = (1, 2, 3, 4, 5) print(tp1[0])
元组为什么不可以进行变化(不是指的手动修改代码)
列表修改示例:
lst1 = [1, 2, 3, 4] num = 0 # 初始值 while True: if num > 5: lst1.append(5) time.sleep(2) # 强制等待的时间,单位:秒 print(f"此时lst1的实际长度为: {len(lst1)}") num += 1 # 每循环一次叠加1 # 问:当数据为lst1的时候,发生长度变化之前,是循环了几次? 6次
元组修改示例:
import time lst1 = [1, 2, 3, 4] # 列表是可以提供变化的 tp1 = (1, 2, 3, 4) num = 0 # 初始值 while True: if num > 5: tp1.append(5) # 报错:'tuple' object has no attribute 'append' time.sleep(2) # 强制等待的时间,单位:秒 print(f"此时lst1的实际长度为: {len(tp1)}") num += 1 # 每循环一次叠加1 # 问题2:既然列表是可以在程序执行之间进行操作,那么换成元组行不行?
问题1:res是由tp1 和 tp2 拼接在一起的,还是额外生成的? -- 额外生成的一个新元组
tp1 = (1, 2, 3, 4) tp2 = (100, 3.14) res = tp1 + tp2 print(res) print(type(res))
问题2:元组乘以int类型的数字的res1是打印两次tp1,还是额外生成一个新的元组?
tp1 = (1, 2, 3, 4) tp2 = (100, 3.14) res1 = tp1 * 2 print(res1) print(type(res1))
小测验:如果给你一个元组,需要修改这个里面的数据,怎么做? -- 先转换成列表,修改数据,然后在转化成元组
tp1 = (1, 2, 3, 4) # 获取修改之前的内存地址 print(f"修改之前的内存地址: {id(tp1)}") # 1.先转换成列表 lst1 = list(tp1) # print(lst1) # print(type(lst1)) # 2.修改数据 lst1.append(5) # print(lst1) # print(type(lst1)) # 3.然后在转化成元组 tp1 = tuple(lst1) # 变量的重定义 -- 对变量进行重新赋值 # print(tp1) # print(type(tp1)) # 获取修改之后的内存地址 print(f"修改之后的内存地址: {id(tp1)}") # 问题:修改之前的tp1的内存地址和修改之后的一样么? 不一样,是一个新的元组,只是引用的变量名称是一样的,但是存放的内存地址不一样
问题:谁是元祖类型? -- 每个元素都是需要用逗号分隔开来的
num1 = (1,) num2 = (1) print(type(num1)) # <class 'tuple'> print(type(num2)) # <class 'int'>
集合
集合的定义
定义:由不同的元素组成的一个数据结构,无序排列的
标识符:{ }
关键字:set
特征:无序,元素不能重复,集合和集合之间可以做运算
单个元素的集合定义
set2 = {1,} print(type(set2))
无序排列 -- 存放在内存地址之前是无序的
set1 = {"欢迎", "来到", "七夜", "老师", "的", "课堂", "!"} print(type(set1)) # <class 'set'> print(f"猜一猜,set1集合中的第一个值是? {set1}") print(f"第二次打印无序的集合:{set1}") print(f"第三次打印无序的集合:{set1}") # 随机的结果: <class 'set'> 猜一猜,set1集合中的第一个值是? {'欢迎', '来到', '老师', '课堂', '的', '!', '七夜'} 第二次打印无序的集合:{'欢迎', '来到', '老师', '课堂', '的', '!', '七夜'} 第三次打印无序的集合:{'欢迎', '来到', '老师', '课堂', '的', '!', '七夜'}
集合里面的元素不能重复 -- 自动去重
set2 = {"七夜老师", "三丰老师", "小明老师", "长风老师", "哈米老师", "七夜老师", "三丰老师"} print(set2) # {'三丰老师', '哈米老师', '小明老师', '长风老师', '七夜老师'}
集合的操作
进行强制转换
set1 = {"欢迎", "来到", "七夜", "老师", "的", "课堂", "!"} lst1 = list(set1) print(type(lst1)) print(f"lst1中的第一个值:{lst1[0]}") # 不确定、随机的
问题:如果转换完成后,连续打印,第一次的值和后面N次的值,是一样的么?
答:一样的,原理:存放内存地址之前,是随机的,但是一旦存放了,后续的内容都是固定的
set1 = {"欢迎", "来到", "七夜", "老师", "的", "课堂", "!"} lst1 = list(set1) print(type(lst1)) print(f"lst1中的第一个值:{lst1[0]}") # 不确定、随机的 print(f"lst1第二次打印第一个值:{lst1[0]}") print(f"lst1第三次打印第一个值:{lst1[0]}") print(f"lst1第四次打印第一个值:{lst1[0]}")
集合的添加 -- add()
set1.add("2024") # print(set1)
集合的删除 -- pop(随机删除,因为没有下标)、remove(删除指定的值)
# set1.pop() # 随机删除,因为没有下标 # print(set1) # set1.remove("七夜") # 删除指定的值,如果删除不存在的值,会报错 # set1.remove("七夜") # print(set1) set1.discard("老师") # 提前准备好,想删除的值,删除多次,都不会报错 set1.discard("老师") print(set1)
集合的运算
运算的方式:交集、并集、差集、交叉补集
交集:获取两个集合之间相同的部分 -- intersection
set1 = {"七夜老师", "小明老师"} set2 = {"七夜老师", "长风老师"} print(f"获取两个集合之间相同的部分: {set1.intersection(set2)}") # 获取两个集合之间相同的部分: {'七夜老师'}
并集:合并两个集合,自动去重 -- union
set1 = {"七夜老师", "小明老师"} set2 = {"七夜老师", "长风老师"} print(f"合并两个集合,自动去重: {set1.union(set2)}")
差集:获取集合中,另一个集合没有的内容 -- difference
set3 = {"七夜老师", "高", "富", "帅"} set4 = {"小明老师", "高", "矬", "富"} print(f"获取对方有,但是自己没有的元素: {set3.difference(set4)}")
交叉补集:剔除公有的内容,留下双方独有的内容
set3 = {"七夜老师", "高", "富", "帅"} set4 = {"小明老师", "矮", "矬", "穷"} print(f"剔除公有的内容,留下双方独有的内容: {set3.symmetric_difference(set4)}")
函数
函数的定义
定义:将一段公式/逻辑代码定义在一个特定的标题(函数名称)下,通过一块,或者一行代码来执行固定好的逻辑,而这些代码只有函数被调动的时候才会执行
通俗点:封装一些代码
核心点:函数的定义、函数的调用
函数的定义:封装好的代码,只有在调用的时候,才会执行 -- 定义函数的时候,不会执行函数内部的代码
函数的调用:语法:函数的名称() -- 调用函数,执行函数内部的代码
函数定义
语法规则:
def 自定义的函数名称(): 封装的代码 ... ...
定义函数,如果不进行调用,是不会运行函数内部的代码(注意:自定义的函数名称,不要和python关键字、已存在的函数名称重复)
# 示例:线性脚本 # m = 1 # n = 2 # s = m + n # print(f"m + n 的结果:{s}") # 封装之后,不再是简单的线性脚本 def add1(): # 函数的名称: add1 # 需要封装的代码 m = 1 n = 2 s = m + n print(f"m + n 的结果:{s}")
调用函数 -- 函数的名称() 表示调用函数,也就是执行函数的内部代码
def add1(): # 函数的名称: add1 # 需要封装的代码 m = 1 n = 2 s = m + n print(f"m + n 的结果:{s}") # 调用函数 -- 函数的名称() 表示调用函数,也就是执行函数的内部代码 add1()
函数的参数
定义函数的时候,可以在小括号里面定义一些参数
定义的参数,可以不给值,然后在调用函数的位置,进行传参
def demo1(name, age, addr): print(f""" =====demo1函数里面的参数===== name: {name} age: {age} addr: {addr} """)
位置参数:按照固定的位置进行传参
def demo1(name, age, addr): print(f""" =====demo1函数里面的参数===== name: {name} age: {age} addr: {addr} """) demo1("七夜老师", 18, "湖南长沙")
指定参数:指定固定的参数进行传参
def demo1(name, age, addr): print(f""" =====demo1函数里面的参数===== name: {name} age: {age} addr: {addr} """) demo1(age=18, name="七夜老师", addr="湖南长沙")
默认参数:定义函数的时候,可以设置参数的默认值 -- print函数里面的end='\n'
# def demo2(name="小明老师", age=88, addr=None): # print(f""" # =====demo1函数里面的参数===== # name: {name} # age: {age} # addr: {addr} # """) # # # demo2(addr="湖南长沙", name="七夜老师")
问:默认参数是要么都传,要么就都不传吗?
答:定义函数的时候,如果给部分参数设置了默认值,那么非默认参数也要遵循默认参数的规则,否则得把非默认参数写在默认参数前面
不定长传参:单个*号 和 两个*号
单个*号的参数:args是默认的名称,可以随意修改 -- 元组类型
# def demo3(*args): # print(f"获取到的值:{args}") # print(f"获取值的类型: {type(args)}") # print(args[0]) # # # demo3(1, 2, 3, 4, 5)
两个*号:kwargs是默认的名称,可以随意修改 -- 字典类型
# def demo4(**kwargs): # print(f"获取到的值:{kwargs}") # print(f"获取值的类型: {type(kwargs)}") # # # demo4(name="七夜老师", age=18, addr="湖南长沙")
函数的返回值
注意事项:
1.函数的内部可以写return返回值,或者不写
2.如果不写return,也可以执行,不会报错,但是接收到的值,还是 None
3.如果写了,可以把需要传递的值,传递给调用函数的地方,通过两种方式获取(print、变量)
4.写了return但是没有传值的情况下,获取到的值是 None
5.如果有return返回值的情况下,可以通过两种方式获取
# def add1(): # 函数的名称: add1 # # 需要封装的代码 # m = 1 # n = 2 # s = m + n # print(f"m + n 的结果:{s}") # # # add1() # 想获取s的值,然后进行 + 100的操作? # print(s + 100) # 函数的作用域问题 -- 后面的课程会讲,暂时不讲 # def add2(): # m = 1 # n = 2 # s = m + n # # 不直接写print,因为无法传递数据 # # 通过函数的返回关键字return,把数据传递给调用函数的地方 # return s # add2() # 问题:此时调用函数,会不会打印s的值? -- 不会 # 因为:没有对获取到的s值,进行打印操作 # 方式一:直接通过print打印获取到函数返回值 # print(f"获取到函数内部的s:{add2()}") # 方式二:通过变量接收函数的返回值,然后进行后续的操作 # res = add2() # print(f"res + 100的值:{res + 100}")
# 写了return但是没有传值的情况下,获取到的值是 None # def add3(): # m = 1 # n = 2 # s = m + n # return # 如果不写return,也可以执行,不会报错,但是接收到的值,还是 None # def add4(): # m = 1 # n = 2 # s = m + n # # # # 方式一: # print(add4()) # # # 方式二: # res = add4() # print(res) # lst1 = [1, 2, 3] # print(lst1.extend("七夜"))
课后作业
遇到的问题
1、pycharm中输入代码后会出现闪动的黑白方块
在键盘中点击一次“insert”键则会自动消失
2.获取两个数的最大值
max(num1,num2)
3.函数内部的变量需要定义后使用 (suum=0)
def sum(*args): suum=0 for i in args: suum = suum +i return suum
4.return不打印返回值,print会打印返回值
5.""" """,可以是注释也可以是多行字符串输出
七、函数相关知识
函数的注释与嵌套
函数的注释
函数的注释与普通注释的区别:用来说明当前函数的参数含义
param 参数名: 参数的注释信息
return: 函数的返回值
def fun1(name): """ :param name: 参数的注释信息 :return: 函数的返回值 """ print("fun1函数") # 查看源码的快捷键:Ctrl + 左键 点击要查看的函数 def fun2(name, age, addr, sal): """ :param name: 请输入姓名 :param age: 请输入年龄 :param addr: 请输入地址 :param sal: 请输入薪资 :return: 函数执行后的返回信息 """ print("fun2函数") # fun1() # fun2() # lst1 = [1, 2] # lst1.append()
示例二:
def login(user, password): """ :param user: 请输入登录的用户名 :param password: 请输入登录的密码 :return: 返回账号信息校验的结果:True/False """ if user == 'admin' and password == '123456': return True # print(login(user='admin', password='123456')) # login() # 打印函数的注释 print(login.__doc__) print(print.__doc__)
函数的嵌套
一个函数的内部调用另一个函数
# def fun1(): # print("欢迎来到七夜老师的课堂!") # fun2() # 陷入死循环的情况 # # # def fun2(): # print("VIP 234 班级的直播课!") # fun1() # 调用fun1函数 # # # # 问题:想在调用fun2函数的同时,去调用fun1函数? # fun2() # 调用fun2函数
一个函数内部嵌套另一个函数
def fun3(): print("欢迎来到七夜老师的课堂!") def fun4(): print("VIP 234 班级的直播课!") fun4() # 问题1:运行fun3函数,会打印几句话? # fun3() # 如果不调用函数,是不会去运行函数的内部代码的!!! # 问题2:能不能在最外层,调用fun4函数? # fun4() # name 'fun4' is not defined # 在函数的内部定义的函数,不能直接在最外层调用 -- 函数的作用域 # 问题3:那么怎么去调用fun4函数呢? # 应该在fun4函数定义的同级 fun3()
python中的内置函数
作用域函数
作用域:定义的变量和函数在哪个范围内可用
文件和文件之间定义的东西,一般不能直接用
函数内定义的东西,不能在文件中直接使用,哪怕同一个文件也不行
类中定义的东西,只在类的内部生效,不能在文件中直接使用
变量:
全局变量 -- 在当前文件内定义的变量,可以在文件任何地方使用
局部变量 -- 在有效范围内可以调用,出了范围就不能用了
类声明的变量也是一样,类的概念后面再说(8节课)
局部变量在定义的时候可以直接声明为全局变量
# def fun1(): # a = 10 # 问题1:能不能再最外层,直接引用变量a? # print(a) # name 'a' is not defined # 不可以直接引用 # 全局变量 # a = 10 # 定义了一个全局变量a # # # def fun2(): # b = 5 # 局部变量 # # print(a) # print(b) # # # # print(a) # fun2() # 问题2:b变量的作用域是fun2函数的内部 # print(b) # 问题3:如果想把函数内部的局部变量的值,传递到函数的外部进行使用? # def fun3(): # s = 20 # return s # 返回函数的数据、结果给到调用函数的位置 # # # s = fun3() # s1 = s + 100 # print(s1) # 问题4:如果想传递多个的函数内部的参数,怎么办? # def fun4(name, age, addr, sal): # return name, age, addr, sal # # # name, age, addr, sal = fun4(name="七夜老师", age=18, addr="湖南长沙", sal=500) # print(f""" # =====自我介绍===== # name: {name} # age: {age} # addr: {addr} # sal: {sal} # """)
局部变量定义成全局变量
通过global关键字,先声明变量,然后再去赋值
# def fun6(): # b = 5 # 未声明 # global c # 已声明 # c = 6 # # # fun6() # # 哪怕是通过global关键字,转化成全局变量,也不可以直接使用,必须使声明的代码(所在的函数)被执行 (注意) # print(c)
在while里面,定义的全局变量,可以进行变量的重定义
e = 10 while True: e = 5 break print(e)如果在循环内部重新定义这个变量,那么这个全局变量的值就被改变了 # 问题:e最后打印的值? a = 1 a = 2 print(a)
数学函数
abs() 绝对值
divmod() 返回商和余数
round() 四舍五入(银行家算法)
pow() 次方
sum() 求和
min() 最小值
max() 最大值
abs() 绝对值
print(abs(-1)) # 1
divmod() 返回商和余数
# x = int(input("请输入一个整型:")) # a, b = divmod(x, 2) # print(f"商:{a}") # print(f"余:{b}")
round() 四舍五入(银行家算法)
奇数:四舍五入,偶数:直接舍去(这个规则,只在0.5区间生效)
# print(round(1.5)) # 2 # print(round(3.5)) # 4 # print(round(5.5)) # 6 # # print(round(2.5)) # 2 # print(round(4.5)) # 4 # print(round(6.5)) # 6 # print(round(4.9)) # print(round(4.6)) # print(round(4.51))
pow() 次方
print(pow(10, 2))
sum() 求和
lst1 = [1, 2, 3, 4, 5, 6, 7] print(sum(lst1))
min() 最小值
print(min(lst1))
匿名函数
匿名函数的定义
匿名函数:就是没有名字的函数
python lambda表达式实现匿名函数
语法规则:
lambda 参数: 逻辑
匿名函数里面的参数名称,是自定义
结果就是返回表达式的结果
示例一:
import math # 导入 # pai = math.pi # print(f"圆周率π: {pai}") # # # 圆的面积计算公式: s = π * r² # r = 5 # 圆的半径 # s = math.pi * pow(r, 2) # print(f"圆的面积: {s}") # 方式一:普通的函数定义 def s_area(r): """ :param r: 圆的半径 :return: 返回圆的面积 """ s = math.pi * pow(r, 2) return s print(f"当r的值为5的时候,圆的面积: {s_area(r=5)}") # 方式二:匿名函数的定义 res = lambda r: math.pi * pow(r, 2) print(f"当r的值为5的时候,圆的面积: {res(r=5)}")
匿名函数的使用
lst1 = [10, 20, 30, 40] res1 = lambda a: min(a) print(f"获取lst1列表中的最小值:{res1(a=lst1)}")
装饰器之函数传递
函数的传递
python中可以把函数当变量传递
所以这种情况下,可以直接执行被传入的函数
主题:函数的引用 和 调用
示例一:
# def fun1(): # print("欢迎来到七夜老师的课堂!") # 函数的调用 -- 函数的名称(),就会执行函数的内部代码 # fun1() # 函数的引用(所在的内存地址) -- 函数的名称,没有小括号 # print(fun1) # <function fun1 at 0x7fbb180c8160>, function代表是一个函数、fun1表示函数的名称、at 0x7fbb180c8160表示函数所在的内存地址 # 问题:函数的调用,与函数的引用之间有什么区别? # 函数的调用有小括号,函数的引用没有小括号
示例二:
def fun1(): print("欢迎来到七夜老师的课堂!") def fun2(fun_name): # 参数的名称可以自定义 """ :param fun_name: 传入函数的引用/本体 :return: 调用传入的这个函数 """ print("这里是VIP 234 班级的直播课堂!") print(f"此时fun_name获取的值:{fun_name}") # fun1函数的引用 -- 引用与调用之间的区别:有没有小括号 fun_name() # 请问:这是在调用哪个函数? -- 调用fun1函数 # 通过函数的引用,来完成,调用fun2函数的时候,去调用fun1函数 fun2(fun_name=fun1) # 把fun1函数,当做变量进行传值
调用
运行这个函数的内部代码
引用
提供这个函数所在的内存地址,然后加上小括号,就可以完成对这个函数的调用
口诀:有小括号叫调用,没有小括号叫引用
在引用函数的时候,不会因为没有传参,而报错
但是在调用函数的时候,会因为没有传参,而报错
def login(username, password): print(f""" ===用户信息=== username: {username} password: {password} """) def fun1(fun_name, value1, value2): print("fun1函数") fun_name(value1, value2) fun1(fun_name=login, value1="admin", value2="123456")
八、装饰器、模块和文件操作
装饰器的详解
日志
程序运行的时候的记录 -- 日志
在实际工作中,python这样的东西,是放在服务器(linux)上运行的
日志其实就是记录下来当前程序的运行,协助我们定位问题
确定问题的方式(通过日志、报错信息去溯源)
import logging # 日志模块
日志模块,会有日志的级别定义
常见的日志级别:
warning:警告---warning和error
error:报错---error
debug:调试---都有
info:正常---没有debug
# 级别是自己设置:我们可以通过自定义级别去确定什么东西该被记录,什么东西不被记录
# 设置的级别,会打印自己以及比自己小的级别信息!!!
# DEBUG > INFO > WARNING > ERROR
logging.basicConfig(level=logging.DEBUG)
日志打印
# logging.info("自定义的info级别的输出内容") # logging.debug("自定义的info级别的输出内容") # logging.warning("自定义的info级别的输出内容") # logging.error("自定义的info级别的输出内容")
日志输出和print打印有一些区别:
# 1.颜色不一样
# 2.语法不一样
# 3.日志打印的时候,会带有用户信息
注意事项:控制台里面的打印,有可能是日志在前,也有可能是print在前(日志和print打印的输出级别没有先后顺序 -- 并行)
def log_info(fun_name): # logging.info("---->日志开始记录<----") # fun_name() # logging.info("---->日志结束记录<----") # log_info() # def fun2(): # print("fun2函数的代码运行!") # 问题:想通过把函数当做变量传值的方式,运行日志函数的时候,也能过打印fun2函数,并且print的信息要放在日志打印的之间? # 1.调用log_info函数 # log_info() # 2.给log_info函数设置参数,用来接收fun2的函数本体 # 3.需要把fun2的函数本体,当做变量传递给log_info的参数fun_name # log_info(fun_name=fun2) # 4.把接收进来的fun2函数本体,在日志打印之间进行调用,也就是fun_name()
装饰器
可以在原有的函数之前、之后进行代码的补充(强化)
语法规则:
def 外层函数(设置一个参数,用来接收调用函数的本体): def 内置函数(): 你要添加的前/后的代码补充 return 内置函数的名称
普通的函数嵌套
# def zsq(): # # def nzhs(): # print("nzhs的打印信息") # # pass # 让程序直接跳过这部分的代码,也不报错 # # nzhs() # # # zsq()
示例:
# def log_zsq(fun_name): # def log_info(): # # print(f"fun_name的值:{fun_name}") # <function fun3 at 0x7fb7d017d430> # # # 既然fun_name的值是fun3函数的本体,那么只要添加一个括号,就可以运行fun3函数的代码 # # fun_name() # # print("1") # fun_name() # print("2") # # return log_info # # # @log_zsq # def fun3(): # print("fun3函数的打印信息!") # # # fun3() # 问题:在不改变fun3函数里面的代码同时,在他的前面/后面加一些代码,怎么办? # 例如:在前面加一个打印"1",在后面加一个打印"2" # 1.在原有函数的头部,添加一个@符号,然后跟着装饰器的函数名称(不要带括号) # 2.获取fun_name的值,应该是什么? -- fun3函数的本体 # 3.调用fun3函数 # 4.按照需求,完成代码的补充
装饰器的传参
# def login_zsq(fun_name): # def login_nzhs(username, password): # print(f"username:{username}") # print(f"password:{password}") # # # if username == "admin" and password == "123456": # # print("账号验证成功,允许登录") # # fun_name(username, password) # 此时在调用fun4函数,但是fun4函数定义了两个参数,并未传值 # # return login_nzhs # @login_zsq # def fun4(username, password): # if username == "admin" and password == "123456": # print("账号验证成功,允许登录") # fun4(username="admin", password="123456") # 调用装饰器的时候,第一次传参,先给谁? # 装饰器里面的内置函数,需要定义参数用来接收 # 既然内置函数可以接收值,那么原函数fun4怎么接收传进来的值? # 在装饰器里面调用原函数执行的时候,把参数同时传递给他
知识点检查
""" 1.定义装饰器的规则 2.怎么调用/使用装饰器 3.怎么接收调用原函数时,传入的值 4.原函数,怎么接收传进来的值 """ # 1.定义装饰器的规则 def login_zsq(fun_name): def login_nzhs(username, password): print(f"username: {username}") print(f"password: {password}") if username == "admin" and password == "123456": print("账号识别成功,允许登录!") user = "七夜老师" sex = "man" age = 18 fun_name(user, sex, age) return login_nzhs # 2.怎么调用/使用装饰器 @login_zsq def fun1(user, sex, age): print(f""" =====自我介绍===== user: {user} sex: {sex} age: {age} """) # 3.怎么接收调用原函数时,传入的值 fun1(username="admin", password="123456") # 4.原函数,怎么接收传进来的值
# 如何打断点,怎么调试代码
# 手动设置中断程序运行的节点 -- 断点
# 断点调试,只生效于DEBUG模式
模块
模块的概念
包(package)和模块(module)
包就是python中的文件夹(图标有小圆点、有一个init.py文件)
模块就是我们的文件名(不包含.py) 举例:模块的概念
示例:
import time # 模块 # print(time.time()) # 当前时间的时间戳 # time.sleep(3) # 强制等待x秒 # from 模块的路径 import ... # from 包/模块 import 方法/函数/类/变量/其他的数据信息... # from time import sleep # from time import * # sleep(3)
文件操作
文件读取
磁盘:C盘... 500G、1TB、4TB
内存:内存地址,临时存储的空间 16G、24G、32G、64G
python 能够直接读取计算机文件 -- txt、excel、docx、csv、yaml...
语法规则:
open('文件路径', mode='读取方式', encoding='编码格式')
mode: r 读取 w 写入 a 追加写入
直接copy的路径,容易存在转义字符的情况,在引号的前面加一个小写的 r -- 防转义
file = open(r'/Volumes/attached/hcedu/vipCourse/pythonBasic/python_code/python_0307_234/day07/03 文件操作/load_txt', mode='r', encoding='utf-8') # 读取文件 -- read() # msg = file.read() # print(f"读取到的内容:{msg}") # 关闭文件 -- close() # file.close() # msg1 = file.read() # print(f"读取到的内容:{msg1}") # 问题:那么此时,msg还有没有值?可以的,因为变量的值已经存储在内存中了 # print(f"读取到的内容:{msg}") # 按行读取 -- readline() # msg2 = file.readline() # print(f"读取到的内容:{msg2}") # 读取所有的内容,按行划分列表元素 -- readlines() # msg3 = file.readlines() # print(f"读取到的内容:{msg3}") # print(len(msg3))
文件写入
# w:覆盖写入
# a: 追加写入
示例:
file = open("/Volumes/attached/hcedu/vipCourse/pythonBasic/python_code/python_0307_234/day07/03 文件操作/load_txt1", mode="a", encoding="utf-8") # w:覆盖写入 # a: 追加写入 # 直接写入 -- write() file.write("这个是我想写入的内容\n") file.write("这个是我想写入的内容\n") file.write("这个是我想写入的内容") file.write("这个是我想写入的内容") file.close() # 养成好习惯
九、异常机制处理
异常机制
try和except
异常:程序无法继续执行了,例如:字符串和数字相加,除以0,对None进行操作
中断当前程序执行,然后打印出红字Exception
error
捕捉异常的方式:关键字
try: 代码块(逻辑) except 异常类型(Exception): 代码块(出异常之后,会执行这里)
示例:
str1 = input("请输入8个长度以外的字符串:") try: print(f"获取输入字符串的第八个值:{str1[7]}") # unexpected EOF while parsing except Exception as e: # 获取异常的信息,然后赋值给变量 e print(f"报错的异常为: {e},请检查!!!") print("欢迎来到七夜老师的课堂!")
注意:
一旦try的代码块运行完成,没有报错,就不会去运行except
当str1没有8个长度的值出现,那么str1[7]的代码是不是会报错?会
可以提前设置异常处理机制,可以清晰的定位问题,并且不妨碍程序运行
获取报异常的信息,并且可以打印出来
try和finally
-
try...except 捕获异常,出异常了执行except代码块的内容
-
try...finally
try: 代码块 finally: 无论异常是否发生,finally代码块内容一定会执行
示例:
try: print("try下面的代码块执行!") print("报错前的代码") n = 1 / 0 # 一定会报错 print("报错后的代码") except: print("except下面的代码块执行!") n = 1 / 0 finally: print("finally下面的代码块执行!") #问题:try执行代码的时候,遇到了报错的代码,那么之前的代码是否会执行?会 #但是,报错后的同级代码,不会运行
注意:
-
无论try和except会不会报错,finally都会执行
-
只有try报错了,才会运行except
-
如果try报错,并且except里面也报错了,会同时打印报错信息
练习:
try: print("最外层 -- try代码块") try: print("里面 -- try代码块") n = 1 / 0 except: print("里面 -- except代码块") n = 1/0 except: print("最外层 -- except代码块") # 问题:如果正常执行,会打印哪几行的代码? # 如果存在多个try、except的嵌套 -- 遵循try和except的运行逻辑,try不报错,就不会运行except # 问题:在最外层的try里面,加了报错代码,会打印哪几行? # 一旦遇到报错的代码,就不会执行同级代码 # 问题:在里面层的try里面,加了报错代码,会打印哪几行? # 里面这层try、except已经做了正常的异常处理之后,就表示try已经全部运行成功
assert异常
断言:预期结果 == 实际结果
断言:用关键字 assert + 表达式(表达式返回一个bool值)
我希望是一个什么结果 -- 元素定位,assert 标签是否存在 True False
如果表达式是False,就会出异常,后面可以加提示
示例:
username = input("请输入登录的账号:")
password = input("请输入登录的密码:")
if username == "admin" and password == "123":
print("欢迎成功登录七夜老师的用户系统!")
assert username == "admin" and password == "123", f"Use case does not pass, please check data! username:{username}, passowrd:{password}"
print("欢迎成功登录七夜老师的用户系统!")# 为什么用例需要用断言来做处理?
# 一条自动化用例,如果代码全部运行通过,没有报错,视为用例通过
# 反之,如果一旦报错,就视为用例失败