python

一、python介绍

python 只是一个编程语言,在工作中需要结合其他的工具使用

  • python + selenium

    • web自动化(功能测试转换为代码)
  • python + appium

    • 移动端(app)自动化
  • python + requests

    • 接口自动化

1、python特点

  • 简单、易学、免费、开源、适用人群广泛
  • 应用领域广泛(自动化测试)

2、python版本

  • python2(2.x 2.7)
  • python3(主流使用的版本,3.6之后的版本)

3、语言的分类

计算机只认识二进制(0、1)
编程语言是人和计算机沟通的语言
编程语言分类:编译型语言,解释型语言

1、编译型

  • 把程序源代码都编译成机器语言(二进制),保存为二进制文件
  • 计算机可以直接运行,执行速度快
  • C,C++,GO,Swift,Object-C…

2、解释型

  • 在程序执行的时候才会一行一行的处理成机器语言
  • 执行速度慢
  • JavaScript ,python,Ruby,PHP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vkW3GhmZ-1659184224031)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220717094446602.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6sq3DAnC-1659184224033)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220717094051804.png)]

4、python环境配置

python 解释器:将我们书写的python代码转换为二进制,建议版本 >= 3.6

pycharm 书写代码的软件,还能运行代码,运行代码的前提是在pycharm软件中配置了解释器
- 组织代码方式:项目(project),简单的理解为一个目录,目录中可以放很多的代码

建议:每天的代码作为一个项目

5、pycharm基本使用

5.1 新建项目

1、打开pycharm
2、选择create new project
3、指定本地的python解释器
4、点击create创建完成

5.2 新建文件

1、进入pycharm项目
2、选中对应项目名,鼠标右击
3、点击new选择培python file
4、自定义文件名然后选择创建

5.3 编写代码运行

1、按语法书写python脚本
2、书写print(“第一个python脚本”)
3、在工具栏或直接运行py脚本

二、python基础

1、print函数

print("hello world")

print()是python中自带的函数,作用在控制台中输出括号中的内容

后续看到这个函数就是输出打印数据的,或者想要在控制台中显示某个内容,就要使用print()函数

print() 主要在学习阶段使用,便于我们确认结果的正确性
在实际工作的代码中,基本不会使用print,会使用其他的内容代替(日志模块)

print() 函数中是什么内容,就会显示什么内容,里边的文字信息,可以使用单引号,也可以使用双引号

print("hello world")
print('hello python')

2、python注释

注释的作用:

  • 使用开发者自己熟悉的语言在程序代码中添加标注或说明
  • 通过注释增强程序代码可读性
  • 注释的内容不会被解释器执行

(1)单行注释

使用 并号空格进行注释(单独一个 # 也可以)

快捷键 CTRL+/

(2)多行注释

多行注释中的内容可以换行书写

多行注释可以使用 3 对单引号或者 3 对双引号,被3对引号包括的内容就是注释的内容
# 单引号注释
'''
注释1
注释2
注释3
'''

# 双引号注释
"""
注释4
注释5
注释6
"""

3、python波浪线和PEP8

  • 红色
    • 红色波浪线是代码的错误,必须处理,代码才能正常运行
    • 代码没有完全写完,也会出现红色波浪线
  • 灰色
    • 灰色波浪线,不会影响代码的正常运行,基本所有的灰色波浪线都是PEP8不规范造成
    • PEP8:是python代码的书写规范,如果不按照这个规范书写,会给灰色波浪线,建议代码的书写按照PEP8规范书写
    • 快捷键:CTRL+alt+L 自动按照PEP8规范
  • 绿色
    • 绿色波浪线,不影响代码正常执行。一般是单词编写错误会出现

4、python变量

(1)变量作用

用来存储数据的(在程序代码中出现的数据,想要保存下来使用,就必须使用变量)

如:测试数据、用户名、密码、验证码

注意:变量必须先定义(保存数据)后使用(取出数据)

(2)定义变量

变量名 = 数据值   #可以理解为 将数据值保存到变量中
# 比如:
name = '张三'  # 定义一个变量 name,存储的数据值是张三

(3)使用变量

变量定义之后,想要使用变量中的数据,直接使用变量名即可

# 使用变量获取数据,打印
print(name)

(4)命名规范

起名字的规范,标识符的规则

  • 必须由字母、数字和下划线组成,并且不能以数字开头

  • 不能使用python中的关键字

    • python自带的已经使用的标识符,具有特殊的作用

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xMVUwRGA-1659184224034)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220717121801312.png)]

  • 区分大小写

  • 命名习惯

    • 见名知义
    • 使用驼峰体
      • 大驼峰:每个单词首字母大写,例如MyName
      • 小驼峰:第二个单词开始首字母大写,例如myName
    • 使用下划线:每个单词之间使用下划线连接,例如my_name

5、python数据类型

(1)数字类型

  • 整型(int):就是整数,即不带小数点的数
  • 浮点型(float):就是小数
  • 布尔类型(Boolean),只有两个值(真True(1)、假False(0))
    • TrueFalse都是python中的关键字,注意大小写
  • 复数类型:4+1i (很少用到)

(2)非数字类型

  • 字符串(string):使用引号引起来的就是字符串
  • 列表(list):[1,2,3,4]
  • 元组(tuple):(1,2,3,4)
  • 字典(dict):{‘name’ : ‘小明’,‘age’ :18 }

(3)type()函数

可以获取变量的数据类型

  • type(变量)
    • 想要将这个变量的类型在控制台显示,需要使用print输出
      • print(type(变量))
# 整形
age = 18
print(type(age))
# 浮点型
height = 1.82
print(type(height))
# 布尔类型
isMen = True
print(type(isMen))
# 字符串类型 使用引号引起来的就是字符串
name = "小明"
print(type(name))

age="20"
print(type(age))

运行结果:

<class 'int'>
<class 'float'>
<class 'bool'>
<class 'str'>
<class 'str'>

6、python输入

获取用户使用键盘录入的内容

(1)input()函数

  • 变量 = input(‘提示的信息’)
    • 代买从上到下执行,遇到input函数之后,会暂停执行,等待用户的输入,如果不输入会一致等待
    • 在输入的过程中,遇到回车,代表本次输入结束
    • 会将你输入的内容保存到等号左边的变量中,并且变量的数据类型,一定是str
result = input("请输入内容:")
print(type(result),result)   # 打印数据类型和数据值

运行结果:
请输入内容:hello workl
<class 'str'> hello workl

(2)类型转换

  • 变量名 = 数据类型(变量名) 例如:age = int(age)
  • int():支持将float类型整数类型的字符串转换为int类型
  • float():支持int数字类型的字符串(包含整型、浮点型)转换为float类型
  • str():支持任何类型转换为str类型
age = input("请输入你的年龄:")
print("age本来的数据类型",type(age))
age1 = int(age)    # 将输入数据类型转换为整型
print("转换后age的类型:",type(age))
print("转换后age1的数据类型",type(age1))

运行结果:
请输入你的年龄:12
age本来的数据类型 <class 'str'>
转换后age的类型: <class 'str'>
转换后age1的数据类型 <class 'int'>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4B0ro4bQ-1659184224035)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220717143932805.png)]

7、python输出

(1)print()函数

print("hello world")

name = xiaoming
age = 19
print(name,age)

(2)格式化输出

按照一定的格式输出内容,在字符串中指定的位置,输出变量中存储的值

  • 在需要使用变量的地方,使用特殊符号占位
  • 使用变量填充占位的数据
  • %格式化输出占位符号
    • %d占位,填充整型数据digit
    • %f占位,填充浮点型数据float
    • %s占位,填充字符串数据string
# 定义变量   姓名、年龄、身高
# 也可以使用input输入
name = "小明"
age = 19
height = 1.70

# 使用格式化输出”我的名字是××,年龄是××,身高是×ד
print("我的名字是%s,年龄是%d,身高是%fm" % (name,age,height))
# 浮点型小数默认显示6位,%.nf为保留n位有效数
print("我的名字是%s,年龄是%d,身高是%.2fm" % (name,age,height))

stu_num = 1 # 学号
# 格式化输出"我的学号是000001"
print("我的学号是%d" % (stu_num))
# %0nd n表示需要换成具体的整数数字,表示整数一共占几位
print("我的学号是%06d" % (stu_num))

num = 90 #考试的及格率
# 格式化输出某次考试的及格率为90%
# 如果格式化中需要显示%,在书写时使用%%即可
print("某次考试的及格率为%d%%" % num)

运行结果:
我的名字是小明,年龄是19,身高是1.700000m
我的名字是小明,年龄是19,身高是1.70m
我的学号是1
我的学号是000001
某次考试的及格率为90%
  • F-string(f字符串的格式化方法)
    • f-string格式化的方法,python版本 >= 3.6
    • 需要在字符串的前边加上f"“或者F”"
    • 占位符号统一变为{}
      • }}|需要填充的变量{}中
# 定义变量   姓名、年龄、身高、学号、及格率
# 也可以使用input输入
name = "小明"
age = 19
height = 1.70
stu_num = 1
num = 90

print(f"我的名字是{name},年龄是{age},身高是{height}m,学号是{stu_num},及格率是{num}%")
print(f"我的名字是{name},年龄是{age},身高是{height:.2f}m,学号是{stu_num:06d},及格率是{num}%")

运行结果:
我的名字是小明,年龄是19,身高是1.7m,学号是1,及格率是90%
我的名字是小明,年龄是19,身高是1.70m,学号是000001,及格率是90%
  • 字符串格式化
    • 字符串.format()
    • 在需要使用变量的地方使用{}占位
    • “{},{},{}”.format(变量1,变量2,变量3)
# 定义变量   姓名、年龄、身高、学号、及格率
# 也可以使用input输入
name = "小明"
age = 19
height = 1.70
stu_num = 1
num = 90

print("我的名字是{},年龄是{},身高是{}m,学号是{},及格率是{}%".format(name,age,height,stu_num,num))
print("我的名字是{},年龄是{},身高是{:.2f}m,学号是{:06d},及格率是{}%".format(name,age,height,stu_num,num))

运行结果:
我的名字是小明,年龄是19,身高是1.7m,学号是1,及格率是90%
我的名字是小明,年龄是19,身高是1.70m,学号是000001,及格率是90%
  • .lower() — 全部小写
    .upper() — 全部大写
    .title() — 各个字符的首字母大写
    .capitalize() — 首字母大写
    .strip() — 删除两边空格
    .lstrip() — 删除左边空格
    .rstrip() — 删除右边空格
    .replace(" “,”") — 删除所有空格
    .split() — 先切分,“”.join() — 再拼接

8、python运算符

(1)算术运算符

场景构建,假设有x,y两个变量,x=10,y=20

运算符描述实例
+x + y = 30
-x - y = -10
*x * y = 200
/x / y = 0.5
//求商x // y = 0
%求余x % y = 10
**2 ** 3 = 8

(2)比较运算符

场景搭建,a的值为10,b的值为20

运算符描述实例
==等于 - 比较对象是否相等(a == b) 返回 False。
!=不等于 - 比较两个对象是否不相等(a != b) 返回 True。
>大于 - 返回x是否大于y(a > b) 返回 False。
<小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。。注意,这些变量名的大写。(a < b) 返回 True。
>=大于等于 - 返回x是否大于等于y。(a >= b) 返回 False。
<=小于等于 - 返回x是否小于等于y。(a <= b) 返回 True。

(3)赋值运算符

运算符描述实例
=简单的赋值运算符c = a + b 将 a + b 的运算结果赋值为 c
+=加法赋值运算符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
//=取整除赋值运算符c //= a 等效于 c = c // a

(4)按位运算符

下表中变量 a 为 60,b 为 13二进制格式如下:

a = 0011 1100

b = 0000 1101

-----------------

a&b = 0000 1100

a|b = 0011 1101

a^b = 0011 0001

~a  = 1100 0011
运算符描述实例
&按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0(a & b) 输出结果 12 ,二进制解释: 0000 1100
|按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。(a | b) 输出结果 61 ,二进制解释: 0011 1101
^按位异或运算符:当两对应的二进位相异时,结果为1(a ^ b) 输出结果 49 ,二进制解释: 0011 0001
~按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1。~x 类似于 -x-1(~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。
<<左移动运算符:运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。a << 2 输出结果 240 ,二进制解释: 1111 0000
>>右移动运算符:把">>“左边的运算数的各二进位全部右移若干位,”>>"右边的数指定移动的位数a >> 2 输出结果 15 ,二进制解释: 0000 1111

(5)逻辑运算符

Python语言支持逻辑运算符,以下假设变量 a 为 10, b为 20:

运算符逻辑表达式描述实例
andx and y布尔"与" - 如果 x 为 False,x and y 返回 x 的值,否则返回 y 的计算值。(a and b) 返回 20。
orx or y布尔"或" - 如果 x 是 True,它返回 x 的值,否则它返回 y 的计算值。(a or b) 返回 10。
notnot x布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。not(a and b) 返回 False

9、python判断(条件控制)

(1)if的基本结构

  • 基本语法

    if 判断条件:
    	书写条件成立(真),执行代码
    	书写条件成立(真),执行代码
    	
    顶格书写,没有缩进的代码,和if无关,不管条件是否成立,都会执行
    
    1、if是一个关键字,和后续的判断条件之间需要一个空格
    2、判断条件后边需要一个冒号,不要少了
    3、冒号之后,回车,代码需要缩进,在pycharm中会自动进行缩进,一般是4个空格或一个tab键
    4、所有在if代码下放的缩进中书写的代码,属于if语句的代码块,判断条件位True的时候会执行
    5、if代码块中的代码,要么都执行,要么都不执行
    6、if代码块结束之后,代码要顶格书写(不再有缩进),表示是和if无关的代码
    

    示例

    # 1、使用input获取用户的年龄
    # 2、判断年龄是否满足18岁
    # 3、如果年龄大于等于18岁,输出满18岁了,可以进入网吧了
    
    age = input("请输入你的年龄:")  # 输入类型为str字符串类型
    if int(age) >= 18:           #字符串和int类型不能比大小,先类型转换再比大小
        print("满18岁了,可以进入网吧了")
    elif int(age) < 18:
        print("未满18岁禁止入内")
    print("我与if判断无关,无论如何我都会执行")
    
    运行结果:
    请输入你的年龄:12
    未满18岁禁止入内
    我与if判断无关,无论如何我都会执行
    

(2)if else结构

  • 基本语法
if 判断条件:
	书写条件成立(真),执行代码
	书写条件成立(真),执行代码
else:
	书写条件成立(真),执行代码
	书写条件成立(真),执行代码
	
1、else是关键字,后边需要冒号
2、冒号之后回车,同样需要缩进
3、处于else代码下方缩进中的内容,属于else的代码块
4、if和else的代码块,只会执行其中的一个
5、else需要结合if使用

示例:

age = input("请输入年龄:")
if int(age) >= 18:
    print("满18岁了,可以进入网吧了")
else:
    print("未满18岁不能入内")

print("我与if else语句无关,会执行")
  • if和逻辑运算符结合使用
# 1、获取用户输入的用户名和密码
# 2、判断用户是admin并且密码是123456时,在控制台输出:登录成功!
# 3、否则再控制台输出:登录信息错误!

admin = input("请输入用户名:")
password = input("请输入密码:")
if admin =="admin" and password == "123456":
    print("登录成功!")
else:
    print("登录信息错误!")
    
运行结果:
请输入用户名:admin
请输入密码:123456
登录成功!
# 1、获取用户输入的用户名
# 2、判断用户名是admin时,在控制台输出:欢迎admin登录!
# 3、用户名是test时,在控制台输出:欢迎test登录!
# 4、如果是其他信息,在控制台输出:查无此人!
username = input("请输入用户名:")

if username == "admin"or username == "test!":
    print("欢迎" + username + "登录!")
else:
    print("查无此人!")

(3)if elif else结构

如果判断条件有多个,建议使用if elif else结构来实现

  • 基本语法

    if 判断条件1:
    	判断条件1成立,执行代码
    elif 判断条件2:          #只有判断条件1不成立,才会判断条件2
    	判断条件2成立,执行代码
    elif 判断条件3:
    	判断条件1、2不成立,判断条件3成立,执行代码
    ...
    else:
    	以上条件都不成立,执行代码
    
    1、elif也是关键字,后边和判断条件之间许哟啊一个空格,判断条件之后需要冒号
    2、冒号之后回车需要缩进,处在这个缩进中的代码代表是elif的代码块
    3、在一个if判断中,可以有很多个elif
    4、只有if的条件不成立,才会去判断elif的条件
    5、在一个if中,如果有多个elif,只要有一个条件成立,后续的所有都不再判断
    
    if 判断条件1:
    	执行的代码
    if 判断条件2:
    	执行的代码
    if 判断条件3:
    	执行的代码
    ...
    
    6、多个if的结构,每个if都会进行判断,之间没有关联
    

    示例:

    # 1、定义score变量记录考试分数
    # 2、如果分数大于等于90分,显示成绩优秀
    # 3、如果分数大于等于80分且小于90分,显示成绩良好
    # 4、如果分数大于等于70分且小于80分,显示成绩中等水平
    # 5、如果分数大于等于60分且小于70分,显示成绩较差
    # 6、其他分数显示成绩不及格
    
    score = input("请输入分数:")
    if 0 <= int(score) <= 100:
        if int(score) >= 90:
            print("成绩优秀")
        elif 80 <= int(score) <90:
            print("成绩良好")
        elif 70 <= int(score) < 80:
            print("成绩中等水平")
        elif 60 <= int(score) <70:
            print("成绩较差")
        else:
            print("成绩不及格")
    else:
        print("输入分数格式错误!")
    

(4)if嵌套

if嵌套,是指在一个if(elif、else)中嵌套另一个if
使用场景:判断条件存在递进关系(只有第一个条件满足了,才会判断第二个条件)
  • 语法
if 判断条件1
	判断条件1成立,执行的代码
	if 判断条件2
		判断条件2成立,执行的代码
	else:
		判断条件2不成立,执行的代码
else:
	判断条件1不成立,执行的代码

示例1:

# 取款机取钱的过程,假定你的密码是123456,账户余额为1000
# 1、提示用户输入密码
# 2、判断密码是否正确
# 3、密码正确后,提示输入取款的金额
# 4、判断取款的金额和余额的关系
password = int(input("请输入密码:"))
SumMoney = 1000
if password == 123456:
    money = int(input("请输入取款金额:"))
    if money > SumMoney:
        print("您的取款金额超出余额范围,请重试!")
    elif money < SumMoney:
        print(f"取款成功,余额剩余{SumMoney-money}")
else:
    print("密码错误!请重试!")
    
运行结果:
请输入密码:123456
请输入取款金额:900
取款成功,余额剩余100

示例2:

# 假定某网站用户名固定为admin,密码固定为123456,验证码固定为8888
# 1、获取用户输入的用户名,密码和验证码
# 2、先判断验证码是否正确,如果正确打印输出验证码正确,再判断用户名和密码是否正确
# 3、如果验证码不正确,直接输出 验证码不正确,请重新输入
user = input("请输入用户名:")
pwd = input("请输入密码:")
vcode = input("请输入验证码:")

if vcode == "8888":
    print("验证码正确!")
    if user == "admin" and pwd == "123456":
        print("登录成功")
    else:
        print("用户名或密码错误,请重新输入!")
else:
    print("验证码错误,请重新输入!")

示例2:猜拳游戏

剪刀石头布

案例步骤:
1、玩家出拳(石头(1)/剪刀(2)/布(3)) input  (player)
2、电脑随机出拳(待完成)(computer)
3、判断输赢:
	- 玩家胜利:
		- player == 1 and computer == 2
		- player == 2 and computer == 3
		- player == 3 and computer == 1
	- 平局:
		- player == computer
	- 玩家失败:
		- player == 1 and computer == 3
		- player == 2 and computer == 1
		- player == 3 and computer == 2
	
随机出拳:
在python中想要随机获取整数数字可以使用如下方法:
1、导入随机数工具包
import random
2、使用工具包中的工具产生指定范围内的数字
random.randint(a,b)   //产生[a,b]之间的随机整数,包含a,b

程序代码:

import random
# (石头(1)/剪刀(2)/布(3))
player = int(input("玩家输入:"))
computer = random.randint(1,3)
print(f"电脑随机生成数:{computer}")
if (player == 1 and computer == 2) or (player == 2 and computer == 3) or (player == 3 and computer == 1):
    print("玩家胜利!")
elif player == computer:
    print("平局")
elif (player == 1 and computer == 3) or (player == 2 and computer == 1) or (player == 3 and computer == 2):
    print("玩家失败!")
else:
    print("输入错误!")

(5)Debug调试代码

debug在代码中出现问题错误(bug),可以使用debug来调试代码,查找错误
我们使用debug主要用来查看代码的执行步骤
  • 打断点

    • 在pycharm中,代码和行号之间进行点击,出现小红点即打断点,再次带年纪小红点会取消断点
    • 断点的位置,一般来说会在代码的第一行(在程序运行的时候,想要在什么地方停下来)
    • 注意点:可能会出现的bug(pycharm软件的问题):代码中只有一个断点的时候不能debug调试查看代码执行过程,解决方案,在代码其他任意地方多加一个断点

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MPAEI5SM-1659184224036)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220718122529182.png)]

  • 右键debug运行代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2gLyxpST-1659184224036)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220718122801791.png)]

  • 单步执行代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nq3IIibv-1659184224037)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220718122858441.png)]

10、python循环

(1)程序的三大流程

  • 顺序:从上向下,顺序执行代码
  • 分支:根据条件判断,决定执行代码的分支
  • 循环:让特定代码 重复执行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TtfGo0i1-1659184224037)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220718152938276.png)]

(2)while循环

作用:循环的作用就是让指定的代码重复的执行

应用场景:让执行的代码按照指定的次数重复执行

  • 基本语法
    • 设置循环的初始条件
    • 书写循环的判断条件
while 判断条件:
	需要重复执行的代码
	改变循环的初始条件
	
注意:while语句以及缩进部分是一个完整的代码块

示例

# 打印100次“hello world”
i = 1
while i <= 100:
    print("hello world")
    i = i + 1
print(f"循环结束后的i:{i}")
  • 死循环和无限循环
死循环:一般是由写代码的人不小心造成的bug,代码一直不停的运行下去

无限循环:写代码的人故意让代码无限制的去执行,代码一直不停的与运行下去
无限循环的使用场景:在书写循环的时候,不确定循环要执行多少次
无限循环的使用一般会在循环中添加一个if判断,当if条件成立,使用关键字break来终止循环
while true:
	if 判断条件:
		break  # 终止循环,当代码执行遇到break,这个循环就不再执行了
	重复执行的代码

示例1:

while True:       # 可以无限玩,直到if判断循环结束为止
    player = int(input("玩家输入:"))
    computer = random.randint(1,3)
    print(f"电脑随机生成数:{computer}")
    if player == 0:
        break     # 循环终止条件
    if (player == 1 and computer == 2) or (player == 2 and computer == 3) or (player == 3 and computer == 1):
        print("玩家胜利!")
    elif player == computer:
        print("平局")
    elif (player == 1 and computer == 3) or (player == 2 and computer == 1) or (player == 3 and computer == 2):
        print("玩家失败!")
    else:
        print("输入错误!")

示例2:

\


# 求1-100数字和
i = 1
sum = 0
while i <= 100:
    sum = i + sum
    i += 1
print(sum)

示例3

# 用循环求1-100偶数和

# 方法1
i = 2
sum = 0
while i <= 100:
	sum = sum + i
	i = i+2
print(sum)

# 方法2
i = 1
sum = 0
while i <= 100:
	if i % 2 == 0:
		sum = sum + i
	i = i + 1
print(sum)

(3)for循环

  • 作用:

    • for循环可以让指定的代码重复执行
    • for循环可以遍历容器中的数据
      • 遍历:从容器中把数据一个一个取出
      • 容器:可以简单理解为盒子,盒子中可以存放很多的数据(字符串str、列表list、元组tuple、字典dict)
    • for循环也可以成为for遍历
  • 基本语法:

    for 变量名 in 容器:
    	重复执行的代码
    	
    # 1、for 和 in 都是关键字
    # 2、容器中有多少个数据,循环会执行多少次(0个数据,执行0次)
    # 3、每次循环,会将容器中数据取出一个保存到in关键字前边的变量中去
    
    # 定义字符串
    my_str = "hello"
    # 遍历字符串  字符串中有5个字符,循环就会执行5次
    for i in my_str:     # 每次循环i的值为字符串中的字符
        print("我错了!",i)    # 重复执行的代码
        
    运行结果:
    我错了! h
    我错了! e
    我错了! l
    我错了! l
    我错了! o
    
  • for做指定次数的循环

for 变量 in range(n):
    重复执行的代码
    
# 1、range()是python中的函数,作用使用可以生成[0,n)之间的整数,不包含n的,一个有n个数字,所以这个循环循环n次
# 2、想让for循环循环多少次,n就写几
# 3、变量的值,也是每次循环从[0,n)取出一个值,第一次取的是0,最后取的是n-1(一共取了n次)
for i in range(3):     # 每次循环i的值为字符串中的字符
    print("我错了!",i)    # 重复执行的代码
    
运行结果:
我错了! 0
我错了! 1
我错了! 2
  • range()变形
# 需求:使用for循环获取5到10之间的数字
for 变量 in range(a,b):
	重复的代码
	
# 1、range(a,b)作用是生成[a,b)之间的整数数字,不包含b

(4)break 和 continue

  • break 和 continue是python中的两个关键字,只能在循环中使用

  • break

    • 终止循环,即代码执行遇到break,循环不在执行,立即结束
  • continue

    • 跳过本次循环,即代码执行遇到break,本次循环剩下的代码不再执行,继续下一次循环
    # 1、获取输入的字符串
    # 2、遍历打印这个字符串
    result = input("请输入一个字符串:")
    for i in result:
        if i == 'e':    # 在遍历的时候,如果遇到字符e,则代码不再继续执行
            break
        if i == 'h':    # 本次循环遇到h,跳过,即不打印h
            continue
        print(i)
        
        
    运行结果:
    请输入一个字符串:abchijkelkf
    a
    b
    c
    i
    j
    k
    

(5)容器

容器:也可以成为是数据序列,或者高级数据类型,也是python中的数据类型

容器中可以存放多个数据

# 1、字符串、列表、元组支持加法运算
str = "hello" + "world"
list = [1,2,3] + [4,5,6]
tuple = (1,2,3) + (4,5,6)

# 2、字符串,列表,元组支持乘一个整数
"hello " * 3  # ==>"hello hello hello "
[1,2] * 3  # ==>[1,2,1,2,1,2]
(1,2) * 3  # ==>(1,2,1,2,1,2)

# 3、len()在容器中都可以使用
# 4、in 关键字在容器中都可以使用,注意,在字典中判断的是字典的键是否存在

11、python字符串

(1)字符串

  • 字符串是容器,因为字符串中可以包含多个字符

  • 定义:使用引号(单、双、三)引起来的内容都是字符串

  • 字符串本身包含单(双)(三)引号,则在定义的时候不能使用单(双)(三)引号

    • 使用 \ 转义字符,将字符串本身的引号进行转义
      • \ ’ == ’ \ " == "
  • 字符串前边加上r"" 原生字符串,字符串中的\不会作为转义字符,文件操作会用一下

  • ord(字符)——获取字符对应的ASCII的值

  • chr(ASCII值)——获取对应的字符

(2)下标

  • 下标指字符在字符串中的位置编号,这个编号就是下标

  • 这个编号一般来说都是从左到右进行编号,从0开始(python中支持负数下标(从-1开始))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6QinS0wD-1659184224038)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220719095447773.png)]

  • 下标作用:可以使用下标获取字符串中某个位置的字符
  • 语法:字符串[下标] 获取指定位置的字符
str = "abcdefg"

print(str[0])   # 打印最开始位置的字符
print(str[-1])   # 打印最后一个字符
print(str[2])   #打印下标为2的字符

# 获取字符串中字符的个数(获取字符串的长度)
# len(字符串)  # length(字符串)
num = len(str)
print(num)
print(str[num-1])   #打印最后一个字符

运行结果:
a
g
c
7
g

(3)切片

  • 切片:可以获取字符串中多个字符(多个字符的下标是有规律的,等差数列)
  • 语法:
    • 字符串[开始下标:结束下标(不包含):步长]
      • start是开始位置的下标,end是结束位置的下标(不能取到该位置),step步长,等差数列的差值,所取得相邻字符下标之间得差值,默认是1,可以不写
      • 例如:[1:5:1] # 1 2 3 4
      • [1:5:2] # 1 3
      • [1:5:3] # 1 4
str = "abcdefgh"

print(str[0:3:1])   # 获取abc字符
print(str[0:3])   # 如果步长是1可以不写,最后一个冒号也不写
print(str[:3])   # 如果开始位置为0,可以不写,但是冒号必须有

print(str[5:8])   # 获取fgh字符
print(str[-3:8])
print(str[5:])   # 如果最后一个字符也要取,可以不写,但是冒号要有
print(str[:])   # 如果开始和结束都不写,获取全部内容,但是冒号要有

print(str[0:8:2])   # 获取aceg,步长为2
print(str[::2])   # 如果是从头到尾遍历,可以不写头尾,但是冒号要有

# 特殊应用,步长为负数,开始和结束不写,意思全变,一般不用管,只有一种使用场景
# 反转(逆置)字符串
print(str[::-1])

运行结果:
abc
abc
abc
fgh
fgh
fgh
abcdefgh
aceg
aceg
hgfedcba

(4)查找—find

  • 用法:
    • 字符串.find(sub_stu,start,end)
    • 作用:在字符串中查找是否存在sub_str这样的字符串
    • sub_str:要查找的小的字符串
    • start:开始位置,从哪个下标位置开始查找,一般不写,默认是0
    • end:结束位置,查找到哪个下标结束,一般不写,默认是len()
    • 返回(代码执行之后会得到什么,如果有返回,就可以使用变量保存)
      • 如果在字符串中找到了sub_str,返回sub_str第一次出现的下标(sub_str中第一个字符在大字符串中的下标)
      • 如果没有找到,则返回-1
mystr = "hello world and itcast and ithemia and python"
num = mystr.find("and")
print(num)   # 查找第一个and出现的下标

num1 = mystr.find("and",num + 1)
print(num1)   # 查找第二个and出现的下标,从第一次出现的后一位开始找

num2 = mystr.find("and",num1+1)
print(num2)   # 查找第三个and出现的下标,从第二次出现的后一位开始找

num3 = mystr.find("and",num2+1)
print(num3)   # 查找第四个and出现的下标,从第三次出现的后一位开始找

运行结果:
12
23
35
-1

(5)替换—replace

  • 用法

    • 字符串.replace(old_str,new_str,count)
    • 作用:将字符串中old_str替换为new_str
    • old_str:被替换的内容
    • new_str:替换后的内容
    • count:替换的次数,一般不写,默认全部替换
    • 返回:替换之后的完整的字符串,原来的字符串没有发生改变
    str = "good good study"
    
    str1 = str.replace("g","G")  #蒋str中所有的g替换成G
    print("str:",str)
    print("str1:",str1)
    
    str2 = str.replace("good","GOOD",1)  # 将str中的第一个good改为GOOD
    print("str2:",str2)
    
    str3 = str.replace("good","GOOD")  # 将str中的第二个good改为GOOD,先将全部的good改为GOOD
    str3 = str3.replace("GOOD","good",1)   # 再将str3中的第一个GOOD改为good
    print("str3:",str3)
    
    运行结果:
    str: good good study
    str1: Good Good study
    str2: GOOD good study
    str3: good GOOD study
    
    

(6)拆分—split

  • 用法:

    • 字符串.split(sep,max_split)
    • 作用:将字符串按照sep进行分割(拆分)
    • sep:字符串按照什么进行拆分,默认是空白字符(空格,换行、\n,tab键\t)
    • max_split:分割次数,一般不写,全部分割
    • 返回:将一个字符串拆分为多个,存到列表中
    • 如果sep不写,想要指定分割次数,则可以按照以下方式:
      • 字符串.split(max_split = n) # n代表分割次数
    mystr = "hello world and itcast and ithemia and python"
    
    str = mystr.split("and")   # 按照and字符进行拆分
    print(str)
    
    str = mystr.split("and",2)  #按照and字符拆分2次
    print(str)
    
    str = mystr.split()   # 按照空格字符进行拆分
    print(str)
    
    str = mystr.split(maxsplit=1)   # 按照空格字符拆分1次
    print(str)
    
    运行结果:
    ['hello world ', ' itcast ', ' ithemia ', ' python']
    ['hello world ', ' itcast ', ' ithemia and python']
    ['hello', 'world', 'and', 'itcast', 'and', 'ithemia', 'and', 'python']
    ['hello', 'world and itcast and ithemia and python']
    

(7)链接—join

  • 用法:

    • 字符串.join(列表)
    • 括号中的内容主要是列表,可以是其他容器
    • 作用:将字符串插入到列表中每相邻的两个数据之间,组成一个新的字符串
      • 列表中的数据使用逗号隔开
      • 列表中的数据必须都是字符串,否则会报错
    list = ['hello', 'world', 'and', 'itcast', 'and', 'ithemia', 'and', 'python']
    print(list)
    
    str = " ".join(list)
    print(str)
    
    str2 = " and ".join(list)
    print(str2)
    
    运行结果:
    ['hello', 'world', 'and', 'itcast', 'and', 'ithemia', 'and', 'python']
    hello world and itcast and ithemia and python
    hello and world and and and itcast and and and ithemia and and and python
    

小总结:

字符串:

  • 下标:str[3]
  • 切片:字符串[开始下标:结束下标:步长]
  • 查找:字符串.find[查找内容:开始下标:结束下标]
  • 替换:字符串.replace[被替换内容:要替换内容:替换次数]
  • 拆分:字符串.split[按照该内容拆分:拆分次数]
  • 链接:字符串.join(列表)

12、python列表

列表 list,是使用最多的一种容器(数据类型)

列表中可以存储多个数据,每个数据之间使用逗号隔开

列表中可以存放任意类型的数据

  • 定义:

    • 方式一:用[ ]定义,数据之间使用英文逗号分隔
    name_list = []
    name_list = ["zhangsan","lisi","wangwu"]
    
    • 方式二:通过类实例化方式定义
    data_list = list()
    
    # 1、类实例化的方式(不常用)
    # 定义空列表(没有任何数据的列表)
    list1 = list()
    print(type(list1),list1)
    
    # 类型转换list(容器) 将其他的容器转换为列表
    # 转换字符串会将字符串中的每个字符作为一个数据存入到列表中
    list2 = list("hello")
    print(list2)
    
    # 2、直接使用[]定义(常用)
    list3 = ["hello","world","heima","小明"]
    print(list3)
    print(list3[0:2])
    print(len(list3))   # 求列表元素个数
    
    运行结果:
    <class 'list'> []
    ['h', 'e', 'l', 'l', 'o']
    ['hello', 'world', 'heima', '小明']
    ['hello', 'world']
    4
    
  • 列表支持下标和切片,使用方法和字符串一致

    • 区别:列表切片得到的是列表

(1)列表查询—index

  • 用法1:用于查找列表中数据下标的方法

    • 列表.index(数据,start,end)
    • 找到返回第一次出现的下标,没有找到代码直接报错
    list3 = ["hello","world","heima","小明"]
    num = list3.index("hello",0,3)
    print(num)
    
    运行结果:
    0
    
  • 用法2:判断是否存在

    • 判断容器中某个数据是否存在可以使用 in 关键字
    • 数据 in 容器
    • 如果存在返回True,如果不存在,返回False
    # 查找3的下标
    list4 = [1,3,5,7,8,9,6,0]
    num = list4.index(3)
    print(num)
    
    # 查找数字4的下标
    if 4 in list4:
        num1 = list4.index(4)
        print(num1)
    else:
        print("该数字不存在!")
    # 统计数据 4 出现的次数
    if list4.count(4):
        num1 = list4.index(4)
        print(num1)
    else:
        print("该数字不存在2!")
        
    运行结果:
    1
    该数字不存在!
    该数字不存在2

(2)列表添加数据—append、insert、extend

  • 尾部添加(最常用)
    • 列表.append(数据)
    • 将数据添加到列表的尾部
    • 返回:返回的None(关键字,空),一般就不再使用变量来保存返回的内容
    • 想要查看添加后的列表,需要打印的是列表
    • 不支持 变量 = 列表.append(数据)
  • 指定下标位置添加
    • 列表.insert(下标,数据)
    • 在指定的下标位置添加数据,如果指定的下标位置本来有数据,原数据会后移
    • 返回:返回的None(关键字,空),一般就不再使用变量来保存返回的内容
    • 想要查看添加后的列表,需要打印的是列表
  • 列表合并
    • 列表1.extend(列表2)
    • 将列表2中的所有数据逐个添加到列表1的尾部
list1 = [1,3,5,7,9]
list2 = [2,4,6,8,0]
list1.append(11)
print(list1)

list1.insert(5,13)
print(list1)

list5 = list1.extend(list2)  # 会返回none,不需要变量保存
print(list5)

list1.extend(list2)
print(list1)  # 直接打印列表

# 将list2整体添加到list1中
list1.append(list2)
print(list1)

运行结果:
[1, 3, 5, 7, 9, 11]
[1, 3, 5, 7, 9, 13, 11]
None
[1, 3, 5, 7, 9, 13, 11, 2, 4, 6, 8, 0, 2, 4, 6, 8, 0]
[1, 3, 5, 7, 9, 13, 11, 2, 4, 6, 8, 0, 2, 4, 6, 8, 0, [2, 4, 6, 8, 0]]

(3)列表修改操作

  • 用法:

    • 列表[下标] = 数据
    • 字符串中字符不能使用下标修改
    • 如果指定的下标不存在,则程序会报错
    my_list = [1,3,5,7]
    my_list[1] = 9
    print(my_list)
    
    # 修改最后一个位置的数据,改为“hello”
    my_list[-1] = 'hello'
    print(my_list)
    
    运行结果:
    [1, 9, 5, 7]
    [1, 9, 5, 'hello']
    

(4)列表删除操作—pop、remove、clear

在列表中删除中间的数据,后面的数据会向前移动

  • 根据下标删除

    • 列表.pop(下标)
    • 删除指定下标位置对应的数据
    • 下标不写,默认删除最后一个数据(常用)
    • 返回:返回删除的数据
    • del 列表[下标]
  • 根据数据值删除

    • 列表.remove(数据值)
    • 根据数据值删除
    • 返回:None
    • 如果删除的数据不存在,会报错
    • 如果有多个同样的数据,只删除第一个
  • 清空数据(少用)

    • 列表.clear()
    my_list = [1,3,5,7,9,11,13]
    
    num = my_list.pop(2)
    print("被删除的数据:",num)
    print(my_list)
    
    my_list.remove(13)
    print(my_list)
    
    my_list.clear()
    print(my_list)
    
    运行结果:
    被删除的数据: 5
    [1, 3, 7, 9, 11, 13]
    [1, 3, 7, 9, 11]
    []
    

(5)列表反转(倒置)—reverse

  • 字符串中,反转倒置:字符串[::-1]
  • 列表中,列表.reverse()
  • 字符串倒置会生成一个新列表,但不会改变原来列表
  • 列表倒置会改变原列表
mylist = [1,2,3,4,5,6,7,8,9]
list = mylist[::-1]
print(list)

mylist.reverse()
print(mylist)

(6)列表复制—copy

将列表中的数据复制一份,给到一个新的列表

  • 切片:变量 = 列表[ : ]
  • copy:变量 = 列表.copy()
  • 使用场景:
    • 有一个列表,需要修改操作列表中的数据,修改之后,需要原数据进行对比,即原数据不能改

(7)列表排序—sort

列表的排序,一般来说都是对数字进行排序的

  • 列表.sort()

    • 按照升序排序,从小到大
  • 列表.sort(reverse = True)

    • 降序排序,从大到小
  • sorted(my_list) — 正序排列;
    sorted(my_list,reverse = True) — 倒叙排列;
    my_list.sort() — 正序排列;
    my_list.sort(reverse = True) — 倒叙排列;
    my_list.reverse() — 反转排列;
    reversed(my_list) — 反转排列;
list = [1,4,2,6,8,9,10,5,3]
# 升序排序
list.sort()
print(list)
# 降序排序
list.sort(reverse=True)
print(list)

运行结果:
[1, 2, 3, 4, 5, 6, 8, 9, 10]
[10, 9, 8, 6, 5, 4, 3, 2, 1]

(8)列表嵌套

person = [["张三","18","功能测试"],["李四","20","自动化测试"]]
print(len(person))
print(person[0])
print(person[0][1])
print(person[0][0][0])

person[0][1] = "19"
print(person)

# 给李四添加一个性别信息
person[1].append("男")
print(person)
# 将张三的年龄删除
person[0].pop(1)
print(person)

运行结果:
2
['张三', '18', '功能测试']
18[['张三', '19', '功能测试'], ['李四', '20', '自动化测试']]
[['张三', '19', '功能测试'], ['李四', '20', '自动化测试', '男']]
[['张三', '功能测试'], ['李四', '20', '自动化测试', '男']]

(9)列表去重

  • 列表去重:列表中存在多个数据,需求:取出列表中重复的数据

  • 方法1:

    • 遍历原列表中的数据,判断在新列表中是否存在,如果存在,不管,如果不存在放入新的列表中
    • 遍历:for 循环实现
    • 判断是否存在:可以用 in
    • 存入数据:append()
  • 方法2:

    • 在python中还有一种数据类型,称为集合(set)

    • 特点:集合中不能有重复的数据(如果有重复的数据会自动去重)

    • 可以使用集合的特点对列表去重

      • 使用set()类型转换将列表转换为集合类型
      • 再使用list()类型转换将集合转换为列表
      • 缺点:不能保证数据再原列表中出现的顺序(一般可忽略)
      # 方法1:
      my_list = [1,2,3,4,2,3,7,9,4]
      my_list1 = []
      for i in my_list:
          if i not in my_list1:
              my_list1.append(i)
      
      # 方法2:
      print(my_list1)
      my_list = [1,2,3,4,2,3,7,9,4]
      my_list = set(my_list)
      my_list = list(set(my_list))
      print(my_list)
      
      

小总结

  • 列表查询:
    • 列表.index(数据,开始下标,结束下标)
    • 数据 in 容器
  • 列表添加数据:
    • 列表.append(数据) 添加到列表末尾
    • 列表.insert(下标,数据) 在下标位置插入
    • 列表.extend(列表2) 在列表1末尾合并列表2
  • 列表修改:
    • 列表[下标] = 修改内容
  • 列表删除:
    • 列表.pop(下标)
    • 列表.remove(数据)
    • 列表.clear() # 清空列表
  • 列表反转:
    • 列表[::-1]
    • 列表.reverse()
  • 列表复制:
    • 列表[ : ]
    • 列表.copy()
  • 列表排序:
    • 列表.sort() # 升序排序
    • 列表.sort(reverse = True) # 降序排序
  • 列表嵌套:
    • 与多元数组原理一样

13、python元组

  • 元组:tuple,元组的特点和列表非常相似

    • 元组中可以存放任意类型的数据
    • 元组中可以存放任意多个数据

    区别:

    • 元组中的数据内容不能改变,列表中的可以改变
    • 元组使用(),列表使用[ ]

    应用

    • 在函数的传参或者返回值中使用,保证数据不会被修改
  • 定义:

    • 使用类实例化方法
    • 直接使用()方法
    # 1、类实例化方法:
    # 定义空元组(不会使用的)
    my_tuple = tuple()
    print(type(my_tuple),my_tuple)
    
    # 类型转换
    # 可以将列表转换为元组,只需将[],变为(),同时将元组转换列表,健()变为[]
    my_tuple2 = tuple([1,2,3])
    print(my_tuple2)
    
    # 转换字符串,和列表中一样,只是将列表的[]变为()
    my_tuple3 = tuple("hello")
    print(my_tuple3)
    
    # 2、直接使用()定义
    my_tuple4 = (1,"xiaowang",3.14,False)
    print(my_tuple4)
    
    # 特殊点,定义一个只有一个数据的元组时,数据后边必须有一个逗号
    my_tuple5 = (1,)
    my_tuple6 = (1)
    print(my_tuple5)
    print(my_tuple6)
    
    运行结果:
    <class 'tuple'> ()
    (1, 2, 3)
    ('h', 'e', 'l', 'l', 'o')
    (1, 'xiaowang', 3.14, False)
    (1,)
    1
    
  • 常用方法:

    • 元组中的数据不能修改,所以只有查看的方法
    • 元组中可以使用下标和切片获取数据
    • 元组中存在index方法
    • 元组中存在count方法
    • 元组中可以使用 in 操作
    • 以上方法使用和列表list类似

14、python字典

  • 字典dict,字典中的数据是由键(key)值(value)对组成的(键表示数据的名字,值就是具体的数据)

    • 在字典中一组键值对是一个数据,多个键值对之间使用逗号隔开

    • 变量 = {key:value,key:value,…}

    • 一个字典中的键是唯一的,不能重复的,值可以是任意数据

    • 字典中的,一般都是字符串,可以是数字,不能是列表

# 1、使用类实例化方法
my_dict = dict()
print(type(my_dict),my_dict)

# dict() 不能转列表和元组,字符串

# 直接使用{}定义
# 空字典
my_dict1 = {}
print(type(my_dict1),my_dict1)
# 非空字典,小明(name)18(age)1.71(height) True(is_men) 抽烟 喝酒 烫头(hobby)
my_dict2 = {"name":"小明","age":18,"height":1.71,"is_men":True,"like":["抽烟","喝酒","烫头"]}
print(my_dict2)
print(len(my_dict2))

运行结果:
<class 'dict'> {}
<class 'dict'> {}
{'name': '小明', 'age': 18, 'height': 1.71, 'is_men': True, 'like': ['抽烟', '喝酒', '烫头']}
5

(1)字典添加

  • 字典[键] = 数据值

    • 如果键已经存在,就是修改数据值
    • 如果键不存在,就是添加数据(即添加键值对)
    # 定义字典 小明 18 爱好
    my_dict = {"name":"小明","age":18,"hobby":["抽烟","喝酒","烫头"]}
    print(my_dict)
    
    my_dict["sex"] = "男"
    print(my_dict)
    
    my_dict["name"] = "小黄"
    print(my_dict)
    
    my_dict["hobby"].append("学习")
    print(my_dict)
    
    运行结果:
    {'name': '小明', 'age': 18, 'hobby': ['抽烟', '喝酒', '烫头']}
    {'name': '小明', 'age': 18, 'hobby': ['抽烟', '喝酒', '烫头'], 'sex': '男'}
    {'name': '小黄', 'age': 18, 'hobby': ['抽烟', '喝酒', '烫头'], 'sex': '男'}
    {'name': '小黄', 'age': 18, 'hobby': ['抽烟', '喝酒', '烫头', '学习'], 'sex': '男'}
    

(2)字典删除—del、clear

  • 删除指定键值对

    • del 字典[键]
  • 清空字典

    • 字典.clear()
    my_dict = {"name":"小明","age":18,"hobby":["抽烟","喝酒","烫头"]}
    del my_dict["name"]
    print(my_dict)
    
    my_dict.pop("age")
    print(my_dict)
    
    my_dict["hobby"].pop(0)
    print(my_dict)
    
    my_dict.clear()
    print(my_dict)
    
    运行结果:
    {'age': 18, 'hobby': ['抽烟', '喝酒', '烫头']}
    {'hobby': ['抽烟', '喝酒', '烫头']}
    {'hobby': ['喝酒', '烫头']}
    {}
    

(3)字典查询—get

根据键获取对应的值

字典中没有下标的概念,想要获取数据值,要使用key(键)来获取

  • 字典[键]

    • 如果键存在,返回键对应的数据值
    • 如果键不存在,会报错
  • 字典.get(键)

    • 字典.get(键,数据值)
    • 数据值一般不写,默认是None
    • 返回:
      • 如果键存在,返回键对应的数据值
      • 如果键不存在,返回的是括号中书写的数据值(None)
    • 一般建议使用get方法
    my_dict = {"name":"小明","age":18,"hobby":["抽烟","喝酒","烫头"]}
    print(my_dict["name"])
    
    print(my_dict.get("name"))
    
    print(my_dict.get("name1","没有要查找的键就显示我!"))
    
    print(my_dict["hobby"][1])
    
    print(my_dict.get("hobby")[2])
    
    运行结果:
    小明
    小明
    没有要查找的键就显示我!
    喝酒
    烫头
    

(4)字典遍历—keys、values、items

  • 对字典的键进行遍历

    for 变量 in 字典:
    	print(变量)   # 变量就是字典中的key,键
    	
    for 变量 in 字典.keys():   # 字典.keys()可以获取字典中所有的键
        print(变量)
    	
    
  • 对字典的值进行遍历

    for 变量 in 字典.values():   # 字典.values()可以获取字典中所有的值
    	print(变量)
    
  • 对字典的键值进行遍历

    # 变量1就是键,变量2就是键对应的值
    
    for 变量1,变量2 in 字典.items():   # 字典.items()获取键值对
    	print(变量1,变量2)
    
my_dict = {"name":"小明","age":18,"hobby":["抽烟","喝酒","烫头"]}

for i in my_dict:
    print(i)

print("-"*200)

for i in my_dict.keys():
    print(i)

print("-"*200)

for i in my_dict.values():
    print(i)

print("-"*200)

for i,j in my_dict.items():
    print(i,j)
    
运行结果:
name
age
hobby
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name
age
hobby
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
小明
18
['抽烟', '喝酒', '烫头']
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name 小明
age 18
hobby ['抽烟', '喝酒', '烫头']

小总结

  • 字典添加:

    • 字典[键] = 数据值
    • 字典.append(数据值)
  • 字典删除:

    • del 字典[键]
    • 字典.pop(键)
    • 字典.clear() ——清空字典
  • 字典查询

    • 字典[键]
    • 字典.get(键)
  • 字典遍历

    • for i in 字典.keys()——遍历键
    • for i in 字典.values()——遍历值
    • for i,j in 字典.items()——遍历键值

15、python函数

(1)概念

  • 函数就是把具有独立功能的代码块组织为一个小模块,在需要的时候调用
  • 通俗理解,将多行代码写在一块,起个名字,在需要这多行代码的时候,可以直接使用这个名字来代替
  • 作用:减少代码的冗余(重复的代码不用多写),提高程序的编写效率

(2)定义

  • 将多行代码放在一块,起名字的过程,称为函数定义

  • 函数必须先定义后调用

  • 语法

    def 函数名():
    	函数中的代码1
    	函数中的代码2
    
    • def是关键字,用来定义函数的 define的缩写
    • 函数名需要遵守标识符的规则是
    • 处于def缩进中的代码,称为函数体
    • 函数定义的时候,函数体中的代码不会执行,在调用的时候才会执行
  • 函数定义小技巧

    • 在前期,书写不熟练的时候
      • 可以先不管函数,先把功能写出来
      • 给多行代码起名字
      • 选中多行代码,使用tab进行缩进

(3)调用

  • 使用多行代码的时候,称为函数调用

  • 语法

    函数名()
    
    • 函数调用的时候会执行函数体中代码
    • 函数调用的代码,要写在函数体外

(4)文档注释

  • 文档注释的本质,还是注释,只不过书写的位置和作用比较特殊

  • 书写位置,在函数名的下方使用三对双引号进行注释

  • 作用:告诉别人这个函数如何使用的,干什么的

    • 查看,在调用的时候,将光标放在函数名上,使用快捷键CTRL P
    • CTRL+B转到函数声明中查看

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w2xCoyZJ-1659184224039)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220720165115189.png)]

(5)嵌套调用

  • 在一个函数定义中调用另一个函数

    • 函数定义不会执行函数体中的代码
    • 函数调用会执行函数体中的代码
    • 函数体中代码执行结束会回到函数被调用的地方继续向下执行
    def func1():
        print(1)
        print("func1")
        print(2)
    
    def func2():
        print(3)
        func1()
        print(4)
    
    func2()
    
    运行结果:
    3
    1
    func1
    2
    4
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UrBtQvUo-1659184224040)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220720170551564.png)]

(6)函数参数

  • 函数参数:在函数定义的时候,使用变量代替具体的数据值(进行占位),在函数调用的时候,传递具体的数据

  • 好处:让函数更加通用,能够解决一类问题,而不是单纯的一个问题

  • 形式参数:形参,使用变量代替具体的数据,在函数定义时起占位作用

  • 实际参数:实参,具体的数据值,调用函数时,会传递给形参

  • 调用函数时,形参个数必须等于实际参数,否则报错

    # 1、定义一个函数,求两个数字和
    # num1和num2是函数定义时的参数,起到占位的作用,没有具体的数据值,称为形式参数,简称形参
    def sum(num1,num2):
        num = num1 + num2
        print(num)
    
    sum(34,56)   # 在函数调用的时候,括号中的数据会传递给形参,时具体的数据值,称为实际参数,简称实参
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hQ6SI2fM-1659184224040)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220721094749308.png)]

  • 函数的传参方式

    • 位置传参
      • 在函数调用的时候,按照形参的顺序,将实参传递给形参
    • 关键字传参
      • 在函数调用的时候,指定数据值给到哪个形参
    • 混合使用
      • 关键字传参必须写在位置传参的后面
      • 不要给一个形参传递多个数据值
    def func(a,b,c):
        print(f"a:{a},b:{b},c:{c}")
    
    
    # 位置传参
    func(1,2,3)
    
    # 关键字传参
    func(a=2,b=3,c=1)
    
    # 混合使用
    func(1,5,c=4)
    
    运行结果:
    a:1,b:2,c:3
    a:2,b:3,c:1
    a:1,b:5,c:4
    
  • 缺省参数

    • 缺省参数,默认参数
    • 定义方式:
      • 在函数定义的时候,给形参一个默认的数据值,这个形参就变为缺省参数
      • 缺省参数的书写要放在普通参数的后边
    • 特点(好处);
      • 在函数调用的时候,可以传递实参值,也可以不传递实参值
      • 传参,则传递的实参值,不传参,使用的默认值
def show_info(name,sex="保密"):   # 此处sex的参数为默认值,在调用函数的时候,如果没有实参值,则默认值为”保密“
    print(name,sex)

show_info("小王")   # 此处没有给sex传递实参值
show_info("小王","男")  # 此处给sex传递的实参值为”男“

运行结果:
小王 保密
小王 男
  • print()函数中的形参(缺省参数)

    • sep’ ',多个位置参数之间的间隔

    • end=‘\n’ 每一个print函数结束,都会打印的内容,结束符

print定义函数:

def print(self,*args,sep=' ',end='\n',file=name)
  • 多值参数[可变参数/不定长参数]

    • print(1)
      print(1,2)
      print(1,2,3)
      print(1,2,3,4)
      
    • *不定长位置参数(不定长元组参数)——(args)

      • 书写,在普通参数的前边 ,加上一个*,这个参数就变成不定长位置参数
      • 特点:这个形参 可以接收任意多个位置传参的数据
      • 数据类型:形参的类型是元组tuple
      • 不定长位置参数,要写在普通的参数的后面
      • 一般写法,不定长位置参数的名字为args,即(*args) # arguments
    • **不定长关键字参数(不定长字典参数)——****kwargs

      • 书写:在普通 参数的前边,加上两个*,这个参数就变成了不定长关键字参数
      • 特点:这个形参可以接收任意多个关键字传参的数据
      • 数据类型:形参的类型是字典dict
      • 不定长关键字参数,要写在所有参数的最后边
      • 一般写法:不定长关键字参数的名字为kwargs,即(**kwargs) # keyword arguments
    • 如果同时有位置参数和关键字参数,则位置参数分别传到*args,关键字**kwargs

    • 完整的参数顺序

  def 函数名(普通函数,*args,缺省参数,**kwargs)
  	pass
  
  #一般在使用的时候,使用1-2种,按照这种顺序挑选书写即可
def func(*args,**kwargs):
    print(type(args),args)
    print(type(kwargs),kwargs)
    print("-"*30)

func(1,2,3,4)  # 位置传参,数据都给*args
func(a=1,b=2,c=3,d=5)  # 关键字传参,数据都给**kwargs
func(1,2,3,a=6,b=7,c=9)  # 位置和关键字传参,位置给args,关键字给kwargs

运行结果:
<class 'tuple'> (1, 2, 3, 4)
<class 'dict'> {}
------------------------------
<class 'tuple'> ()
<class 'dict'> {'a': 1, 'b': 2, 'c': 3, 'd': 5}
------------------------------
<class 'tuple'> (1, 2, 3)
<class 'dict'> {'a': 6, 'b': 7, 'c': 9}
------------------------------
  • 使用元组和字典进行传参
    • 将字典和列表中的数据使用my_sum函数进行求和,该如何传参?
    • 想要将列表(元组)中的数据,分别作为位置参数进行传参,需要使用*对列表进行拆包操作
      • my_sum(*my_list)
    • 想要将字典中的数据,作为关键字传参,需要使用**对字典进行拆包
      • my_sum(**my_dict)
def my_sum(*args,**kwargs):
    num = 0
    for i in args:
        num += i
    for j in kwargs.values():
        num += j

    print(num)

my_list = [1,2,3,4]
my_tuple = (2,3,4,5,6)
my_dict = {"a":1,"b":2,"c":5,"d":8}

my_sum(*my_list,**my_dict)
my_sum(*my_tuple,**my_dict)

运行结果:
26
36

(7)返回值

  • 函数的返回值,可以理解为是函数整体执行的结果是什么

    • print() ==》None
    • input() ==》键盘输入的内容
    • type() ==》类型
    • len() ==》数据的长度(元素的个数)
  • 在函数中想要将一个数据作为返回值返回,需要使用return关键字(只能在函数中使用)

    • 将数据值作为返回值返回
    • 函数代码执行遇到return,会结束函数的执行
  • 想要将函数中返回的结果,在后续的代码中使用,即需要将这个数据保存下来,需要使用变量来保存函数的返回值(执行结果)

    • 变量 = 函数()
    def sum(a,b):
        num = a + b
        # print(num) # 代码中没有返回值,只有print,这个结果只能在函数中用一次,不能后续使用
        return num # 将这个结果返回到调用的地方
    
    
    # sum(1,2)
    print(sum(1,2)) # 函数中没有print,只有return,想要查看结果,需要在调用的时候使用print
    
    
    # 想要将函数中返回的结果,在后续代码中使用,即需要将这个数据保存下来,需要使用变量来保存函数的返回值(执行结果)
    # 变量 = 函数()
    result = sum(1,2)
    
  • return返回值的说明

    def 函数名():  # 返回值None
        pass
    
    def 函数名():
        return  # return后边没有数据,返回值None
    
    def 函数名():
        return xx  # 返回值是xx
    
    

(8)变量进阶(理解)

  • 变量的引用

    • 变量和数据都是保存在内存中的,python解释器会在内存中分两块空间存储

    • 在python中函数的参数传递以及返回值都是靠引用传递的

    • 本质是将数据的地址保存到变量对应的内存中

    • 变量中存储数据地址的行为就是引用(变量引用了数据的地址,简单说就是变量中存储数据),存储的地址称为引用地址

    • 可以使用id(),获取变量中的引用地址(即数据地址),如果两个变量的id()获取的引用地址一样,即代表两个变量引用了同一个数据

    • 只有 赋值运算符=,可以改变变量的引用(等号左边数据的引用)

  • 可变类型和不可变类型

    • 数据类型:int float bool str list tuple dict set

    • 可变和不可变:数据所在的内存是否允许修改,允许修改就是可变类型,不允许修改就是不可变类型

    • 可变类型:列表(list)、字典(dict)、集合(set)

      • 列表.append()
      • 字典.pop(键)
    • 不可变类型:int float bool str tuple

  • 只有 =,可以改变引用

  • 可变类型 参数,在函数内部,如果不适用 = 直接修改形参的引用

def func(list1):  # list1 = my_list 此时两个变量的引用是相同的
    list11  = [2,1]  #  此时,list1变量的引用发生了变化,问,my_list的引用没有改变,数据不会变

my_list = [1,2]
func(my_list)
print(my_list)

运行结果:
[1, 2]
def func(list1):
    list1 += [1,2]  #对于列表来说,+=本质是extend(列表合并 )操作

my_list = ["a","b"]
func(my_list)
print(my_list)

运行结果:
['a', 'b', 1, 2]

(9)交换两个变量值

# 方法1:常规方法,引用第三个变量
a = 10
b = 20

c = a # 将变量a中 的值先保存在c中
a = b # 将变量b中的值给a
b = c # 将变量c中的值给b

print(a,b)

# 方法2:不使用第三变量,使用数学中的方法
a = a + b  #  a的值为30
b = a - b  #  30 - 20  ==》10
a = a - b  #  30 - 10 ==》20
print(a,b)

# 方法3:重点掌握,python特有
a,b = b,a
print(a,b)
  • 组包和拆包
    • 组包(pack)
      • 将多个数据值使用逗号连接的过程,组成元组
    • 拆包(unpack)
      • 将容器中多个数据值使用多个变量分别保存的过程
      • 变量的个数和容器中数据的个数要保持一致
    • 赋值运算符,都是先执行等号右边的代码,执行的结果,保存到等号左边的变量中
a = 10
b = 20
c = b,a   # 组包
print(type(c),c)

a,b = c  # 拆包
print(a,b)

运行结果:
<class 'tuple'> (20, 10)
20 10

(10)局部变量和全局变量

根据变量的定义位置,可以将变量分为局部变量和全局变量

1)局部变量

  • 局部变量:在函数内部(函数的缩进中)定义的变量,称为是局部变量
  • 特点:
    • 局部变量只能在当前函数内部使用,不能在其他函数和函数外部使用
    • 在不同函数中,可以定义名字相同的局部变量,两者之间没有影响
    • 生命周期(作用范围)——在哪能用
      • 在函数被调用的时候,局部变量被创建,函数调用 结束,局部变量的值被销毁(删除),不能使用
      • 所以函数中的局部变量的值,如果想要在函数外部使用,需要使用return关键字,将这个值及进行返回
def func1():
    num = 10
    print(f"func1中的局部变量值为:{num}")


def func2():
    num = 100   # 可以在不同函数中定义同一名字的局部变量
    print(f"func2中的局部变量值为:{num}")

func1()
func2()
func1()

运行结果:
func1中的局部变量值为:10
func2中的局部变量值为:100
func1中的局部变量值为:10

2)全局变量

  • 全局变量:在函数外部定义的变量,称为是全局变量
  • 特点:
    • 可以在任何函数中读取(获取)全局变量的值
    • 如何在函数中存在和全局变量名字相同的局部变量,在函数中使用的是,局部变量的值(就近)
    • 在函数内部想要修改全局变量的引用,需要添加global关键字,对变量进行生命为全局变量
    • 生命周期:
      • 代码执行的时候被创建,代码执行结束,被销毁(删除)
num = 10

def func1():
     print(num) # 在函数中可以读取全局变量的值


def func2():
    num = 20 # 定义局部变量,不会影响全局变量
    print(num)


def func3():
    global num  # 这个函数中使用的num都是全局变量,一般写在第一行
    num = 30    # 这里是把全局变量的num值改为了30,所以还是三十,前面对应的全局变量全部变为30
    print(num)

func1()
func2()
func3()
func1() # 因为func3()改变了全局变量的值

运行结果:
10
20
30
30

(11)返回多个数据值

  • 返回一个数据值,使用return关键字
  • 将多个数据值组成容器进行返回,一般是元组(组包)
  • 变量 = 函数(数据1,数据2) 此时变量类型为元组类型
def func(a,b):
    num1 = a + b
    num2 = a - b
    return num1,num2
# 方法1:
result = func(10,5) # 此时result为元组
print(type(result),result,result[0],result[1])

# 方法2:直接拆包
x,y = func(20,13)
print(type(x),x,y)

运行结果:
<class 'tuple'> (15, 5) 15 5
<class 'int'> 33 7

(12)匿名函数—lambda

  • 匿名函数:使用lambda关键字定义函数

    • 一般称为使用def关键字定义的函数为 标准函数

    • 匿名函数只能书写一行代码

    • 匿名函数的返回值不需要return ,一行代码(表达式)的结果就是返回值

    • 匿名函数一般不需要我们主动的调用

    • 一般作为函数的参数使用

    • 使用场景:作为函数的参数,这个函数比较简单,值使用一次,没有必要使用def定义

  • 语法:lambda 参数:一行代码

    • 这一行代码称为表达式
# 1、无参无返回值
def func1():
    print("hello world")
func1()
################
lambda :print("hello lambda")
func11 = lambda :print("hello lambda")  #尽量不对lambda表达式赋值,使用def
# 2、无参有返回值
def func2():
    return 10

print(func2())
#################
lambda :10
func22 = lambda :10
print(func22)
# 3、有参无返回值
def my_sum(a,b):
    print(a + b)

my_sum(1,2)
#################
my_sum11 = lambda a,b:print(a+b)
my_sum11(10,29)

# 4、有参有返回值
def func4(a,b):
    return a + b

print(func4(1,2))
#################
func44 = lambda a,b:a+b
print(func44(1,2))
  • 匿名函数作为函数的参数—列表中的字典排序
    • 列表.sort(key = lambda x:x['键 '])——升序
    • 列表.sort(key = lambda x:x['键 '],reverse = True)——降序
user_list = [
    {"name":"zhangsan","age":18},
    {"name":"lisi","age":19},
    {"name":"wangwu","age":12}
            ]
# user_list.sort()
# 列表的排序,默认是对列表中的数据进行比大小的,可以对数字类型和字符串进行比大小
# 但是对于字典来说,就不知道怎么比大小,此时,我们需要使用sort函数中的key这个参数,来指定字典比大小的方法
# key这个参数,需要传递一个函数,一般是匿名函数,字典的排序,其实要指定根据字典的什么键进行排序,我们只需要使用匿名函数返回字典的这个键对应的值即可

# 根据年龄排序
user_list.sort(key = lambda x: x["age"])
print(user_list)

# 说明:匿名函数中的参数x是列表中的(字典)数据,在sort函数内部,会调用key这个函数(将列表中每个数据作为实参传递给形参)
# 从列表中的获取函数的返回值,对返回值进行比较大小操作

三、python进阶

1、面向对象

(1)基本介绍

  • 面向对象是一个编程思想(写代码的套路)
  • 编程思想:
    • 面向过程
    • 面向对象
    • 都属于写代码的套路(方法),最终目的都是为了将代码书写出来 ,
    • 过程与思考方法不太一样
  • 面向过程
    • 关注的是具体步骤的实现,所有的功能都自己书写
    • 亲历亲为
    • 定义一个个函数,最终按照顺序调用函数
  • 面向对象
    • 关注的是结果,谁(对象)能帮我做这件事
    • 偷懒
    • 找一个对象,让对象去做

(2)类和对象

  • 面向对象的核心思想是,找一个对象去帮我们处理事情

  • 在程序代码中,对象是由类创建的

  • 类和对象,是面向对象编程思想中非常重要的概念

    • 抽象的概念,对多个特征和行为相同或者相似事务的统称
    • 特征称为属性
    • 行为称为方法
    • 泛指的(指代多个,而不是具体的一个)
  • 对象

    • 是由类创建的,具体存在的一个 事物,看得见摸得着的
    • 特指的,(指代一个)
  • 类和对象的关系

    • 类是模板,对象是根据类这个模板创建出来的,应该先有类,再有对象
    • 类只有一个,而对象可以有很多个
      • 不同的对象之间,属性可能会各不相同
    • 类中定义了什么属性和方法,对象中就有什么属性和方法,不可能多,也不可能少

(3)类的组成

  • 类名
    • 给这多个事物起一个名字
    • 在代码中,满足大驼峰命名法(每个单词的首字母大写)
  • 属性
    • 事物的特征,一般文字中的名词
  • 方法
    • 事物的行为,即能做什么事,一般是动词(一般函数定义)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x5imQGlC-1659184224041)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220722203241182.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zYNCGFWy-1659184224042)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220722203519023.png)]

(4)类的抽象(类的设计)

  • 类的抽象,其实就是找到类的 类名、属性和方法

(5)面试代码的步骤

  • 定义类,在定义类之前先设计类

    • 先定义简单的类,不包含属性,在python中定义类需要使用关键字class
    • 方法:方法的本质是在类中定义的函数,只不过,第一个参数是self
    class 类名
    	# 在缩进中书写的内容,都是类中的代码
    	def 方法名(self):  # 就是一个方法
    		pass
    
  • 创建对象,使用第一步定义的类创建对象

    • 创建对象使用类名(进行创建),即
    类名() # 创建一个对象,这个对象在后续不能使用
     # 创建的对象想要在后续的代码中继续使用,需要使用一个变量,将这个对象保存起来
     
    变量 = 类名() #这个变量中保存的是对象的地址,一般可以称为这个变量为对象
    
    # 一个类可以创建多个对象,只要出现 类名()就是创建一个对象,每个对象的地址是不一样的
    
  • 通过对象调用方法

对象.方法名()

列表.sort()
列表.append()
class cat:
    def eat(self):   # self会自动出现,暂不管
        print("小猫爱吃鱼")
    def drink(self):
        print("小猫要喝水")
# 创建对象,可以创建无限个对象
small_cat = cat()
# 通过对象调用类中的方法
small_cat.eat()
small_cat.drink()

运行结果:
小猫爱吃鱼
小猫要喝水

(6)self的说明—对象

class cat:
    def eat(self):   # self会自动出现,暂不管
        print("小猫爱吃鱼")
        
small_cat = cat()
small_cat.eat()
  • 从函数的语法上将,self是形参,就可以是任意的变量名,只不过我们习惯性将这个形参写作self
  • self是普通的形参,但是在调用的时候没有传递实参值,原因是,python解释器在执行代码的时候,自动的将调用这个方法的对象传递给了self,即self的本质是对象
  • 验证,只需要确定通过哪个对象调用,对象的引用和self的引用是一样的
  • self是函数中的局部变量,直接创建的对象是全局变量
class cat:
    def eat(self):
        print(f"{id(self)},self地址")

blue_cat = cat()
blue_cat.eat()
print(f"{id(blue_cat)},blue_cat地址")

print("-"*50)
black_cat = cat()
black_cat.eat()
print(f"{id(black_cat)},black_cat地址")

运行结果:
2120273760016,self地址
2120273760016,blue_cat地址
--------------------------------------------------
2120273756992,self地址
2120273756992,black_cat地址

(7)对象的属性操作

  • 添加属性

    • 对象.属性名 = 属性值
    • 类内部添加
      • 在内部方法中,self是对象
      • self.属性名 = 属性值
      • 在类中添加属性一般写在_ init _方法中
    • 类外部添加
      • 对象.属性名 = 属性值 # 一般不使用
  • 获取属性

    • 对象.属性名
    • 类内部
      • 在内部 中,self是对象
      • self.属性名
    • 类外部
      • 对象.属性名 # 一般很少使用
class cat:
    def eat(self):
        print(f"{id(self)},self地址")
        print(f"小猫{self.name}爱吃鱼...")

blue_cat = cat()
print(f"{id(blue_cat)},blue_cat地址")
blue_cat.name = "蓝猫"
blue_cat.eat()


print("-"*50)
black_cat = cat()
print(f"{id(black_cat)},black_cat地址")
black_cat.name = "黑猫"
black_cat.eat()

运行结果:
2115323891568,blue_cat地址
2115323891568,self地址
小猫蓝猫爱吃鱼...
--------------------------------------------------
2115323891472,black_cat地址
2115323891472,self地址
小猫黑猫爱吃鱼...

2、魔法方法

  • python中有一类方法,以两个下划线开头,两个下划线结尾,并且满足某个条件的情况下,回自动调用,这类方法称为魔法方法

(1)__ init __方法

  • 什么情况下自动调用
    • 创建对象之后会自动调用
  • 有什么用,用在哪
    • 给对象添加属性的(初始化方法,构造方法)
    • 某些代码,在每次创建对象之后,都要执行,就可以将这行代码写在__ init __方法
  • 书写的注意事项
    • 注意不要写错(不要写成int)
    • 如果init方法中,存在除了self之外的参数,在创建对象的时候必须传参
# 猫类,属性 name,age,show_info(输出属性信息)
class Cat:
    def __init__(self,name,age):  # 创建对象之后会被调用
        self.name = name  # 给对象添加name属性
        self.age = age # 给对象添加age属性
        print("我是__ini  t__方法,被调用了")


    def show_info(self):
        print(f"小猫的名字是{self.name},年龄是{self.age}")


# 创建对象,不要在自己类缩进中创建
blue_cat = Cat("蓝猫",2)  # 创建对象,会调用__int__函数
blue = blue_cat   # 不是创建对象,不会调用,这里表示同一个对象,两个名字
blue.show_info()

输出结果:
我是__int__方法,被调用了
小猫的名字是蓝猫,年龄是2

(2)__ str __方法

  • 什么情况下自动调用
    • 使用print(对象)打印对象的时候,会自动调用
  • 有什么用,用在哪
    • 在这个方法中一般书写对象的属性信息的,即打印对象的时候想要查看什么信息,在这个方法中进行定义的额
    • 如果类中没有定义__ str __方法,print(对象),默认输出对象的引用地址
  • 注意事项:
    • 这个方法必须返回一个字符串
# 猫类,属性 name,age,show_info(输出属性信息)
class Cat:
    def __init__(self,name,age):  # 创建对象之后会被调用
        self.name = name  # 给对象添加name属性
        self.age = age # 给对象添加age属性
        print("我是__init__方法,被调用了")

    def __str__(self):
        # 方法必须返回一个字符串
        return f"小猫的名字是{self.name},年龄是{self.age}"

    def show_info(self):
        print(f"小猫的名字是{self.name},年龄是{self.age}")


# 创建对象,不要在自己类缩进中创建
blue_cat = Cat("蓝猫",2)  # 创建对象,会调用__int__函数

print(blue_cat)  # 使用print(对象),会自动调用__str__
blue = blue_cat   # 不是创建对象,不会调用,这里表示同一个对象,两个名字
blue.show_info()

(3)__ del __方法

  • 对象被删除销毁时,自动调用的(遗言,处理后事)(析构方法)
  • 调用场景
    • 程序代码运行结束,所有对象都被销毁
    • 直接使用del删除对象(如果对象有多个名字(多个对象引用一个对象),需要把所有的对象删除才行)
class demo:
    def __init__(self,name):
        print("我是__init__,我被调用了")
        self.name = name

    def __del__(self):
        print(f'{self.name}没了,给它处理后事')

a = demo("a")
b = demo("b")
del a
print("代码运行结束!")

运行结果:
我是__init__,我被调用了
我是__init__,我被调用了
a没了,给它处理后事
代码运行结束!
b没了,给它处理后事
class demo:
    def __init__(self,name):
        print("我是__init__,我被调用了")
        self.name = name

    def __del__(self):
        print(f'{self.name}没了,给它处理后事')

a = demo("a")
c = a
b = demo("b")
del a,c
print("代码运行结束!")

3、封装

  • 封装是面向对象编程的有一大特点

  • 面向对象编程的第一步——将属性和方法封装到一个抽象的类中

  • 外界使用类创建对象,然后让对象调用方法

  • 对象方法的细节都被封装在类的内部

  • 案例1:

    • 小明 体重 75.0公斤
    • 小明每次跑步会减肥0.5公斤
    • 小明每次吃东西体重增加1公斤
    • 类:人类 person 属性:姓名name,体重weight
    • 方法:跑步run(),吃东西eat(),添加属性__ init __ (),属性信息 __ str __
class person:
    def __init__(self,name,weight):
        self.name = name
        self.weight = weight

    def __str__(self):   # 每当需要调用是,需要使用print()函数输出
        return f"体重为:{self.weight}"

    def run(self):
        self.weight -= 0.5

    def eat(self):
        self.weight += 1

person1 = person("小明",75.0)
print(f"开始体重为:{person1}")
person1.run()
print(f"跑步后的体重为:{person1}")
person1.eat()
print(f"吃东西后的体重为:{person1}")

运行结果:
开始体重为:体重为:75.0
跑步后的体重为:体重为:74.5
吃东西后的体重为:体重为:75.5
  • 案例2
    • 房子(House)有户型、总面积和家具名称列表
      • 新房子没有任何的家具
    • 家具(HouseItem)有名字和占地面积,其中
      • 席梦思(bed)占地 4 平米
      • 衣柜(chest)占地 2 平米
      • 餐桌(table)占地 1.5 平米
    • 将以上三件家具添加到房子中
    • 打印房子时,要求输出:户型、总面积、剩余面积、家具名称列表
      • 剩余面积
        • 在创建房子对象时,定义一个剩余面积的属性,初始值和总面积相等
        • 当调用add_item方法,向房间添加家具时,让剩余面积 -=家具面积
    • 类名:房子House
    • 属性:户型name、总面积total_area、剩余面积free_area、家具名称列表item_list = [ ] (新房子)
    • 方法:__ init __ , __ str __、添加家具方法add_item()
    • 类名:家具类HouseItem
    • 属性:名字name,占地面积item_area
    • 方法:__ init __ , __ str __、
class House:
    def __init__(self,house_name,total_area):
        self.house_name = house_name
        self.total_area = total_area
        self.free_area = total_area
        self.item_list = []

    def __str__(self):
        return f"户型:{self.house_name},总面积:{self.total_area}平米,剩余面积:{self.free_area}" \
                f"家具名称列表:{self.item_list}"

    def add_item(self,item):
        # 判断房子的剩余面积和家具的占地面积之间的关系
        # self表示的房子对象,缺少一个家具对象,使用传参解决
        if self.free_area > item.item_area:
            self.item_list.append(item.item_name)
            self.free_area -= item.item_area
        else:
            print("剩余面积不足,换个大房子吧")



class HouseItem:
    def __init__(self,item_name,item_area):
        self.item_name = item_name
        self.item_area = item_area

    def __str__(self):
        return f"家具名字:{self.item_name},占地面积:{self.item_area}平米"
# 创建家具对象
bed = HouseItem("席梦思",4)
chest = HouseItem("衣柜",2)
table = HouseItem("餐桌",1.5)
print(bed)
print(chest)
print(table)
# 创建房子对象
house = House("三室一厅",150)
print(house)
house.add_item(bed)
print(house)

运行结果:
家具名字:席梦思,占地面积:4平米
家具名字:衣柜,占地面积:2平米
家具名字:餐桌,占地面积:1.5平米
户型:三室一厅,总面积:150平米,剩余面积:150家具名称列表:[]
户型:三室一厅,总面积:150平米,剩余面积:146家具名称列表:['席梦思']
  • 案例3:
  • 某web项目登录页面包含:用户名、密码、验证码、登录按钮和登录的方法
  • 书写代码实现以上功能,登录方法中使用print输出即可
    • 类名:LoginPage
    • 属性:用户名username,密码password,验证码code,登录按钮button
    • 方法:登录(login) __ init __
class LoginPage:
    def __init__(self,username,password,code):
        self.username = username
        self.password = password
        self.code = code
        self.button  = "登录"

    def login(self):
        print(f"1、输入用户名:{self.username}")
        print(f"2、输入密码:{self.password}")
        print(f"3、输入验证码:{self.code}")
        print(f"4、点击登录:{self.button}")

user1 = LoginPage("小明","123456",9988)
user1.login()

运行结果:
1、输入用户名:小明
2、输入密码:123456
3、输入验证码:9988
4、点击登录:登录

4、私有和公有

  • 在python中定义的方法和属性,可以添加访问控制权限(即在什么地方可以使用这个属性和方法)

  • 访问控制权限分为两种,公有权限,私有权限

  • 公有权限

    • 直接书写的方法和属性,都是公有的
    • 公有的方法和属性,可以在任意地方访问和使用
  • 私有权限

    • 在类内部,属性名或者方法名前边加上两个下划线,这个属性或者方法就变为私有的
    • 私有的方法和属性,只能在当前类的内部使用
    • 私有的本质是python解释器执行代码,发现属性名或者方法名前有两个_,会将这个名字重命名
      • 例如,self.__ age ==> self. _person__age
  • 什么时候定义私有

    • 某个属性或者方法,不想在类外部被访问和使用,就将其定义为私有即可
    • 测试中,一般不怎么使用,直接公有即可
    • 开发中,会根据需求文档,确定什么作为私有
  • 如果想要在类外部操作私有属性,方法是在类内部定义公有的方法,通过这个方法去操作

  • 对象.__ dict __ 魔法属性,可以将对象具有的属性组成字典返回

  • 案例1

class person:
    def __init__(self,name,age):
        self.name = name   # 姓名
        # self.age = age   # 年龄  # 属于公有属性,外部可以调用
        # 私有的本质,是python解释器执行代码,发现属性名或者方法名前有两个_,会将这个名字重命名
        # 会在这个名字的前边加上 _类名前缀,即self.__age ==>self.person__age
        self.__age = age   # 年龄,将其定义为私有属性,属性名前加上两个_

    def __str__(self):
        return f"名字:{self.name},年龄:{self.__age}"

person1 = person("小明",18)
print(person1)

print(person1.__dict__)
# 在类外部直接访问age属性
# print(self.age) # 公有属性时可以正常访问
# print(self.__age) #变为私有属性时访问失败,会报错
person1.__age = 20  # 这个不是修改私有属性,是添加了一个公有的属性__age
print(person1.__dict__)

print(person1)

print(person1._person__age) # 可以用但建议不要用
person1._person__age = 19
print(person1)

运行结果:
名字:小明,年龄:18
{'name': '小明', '_person__age': 18}
{'name': '小明', '_person__age': 18, '__age': 20}
名字:小明,年龄:18
18
名字:小明,年龄:19

5、继承

  • 封装 根据职责将属性和方法封装到一个抽象的类中

  • 继承 实现代码的重用,相同的代码不需要重复的编写

  • 多态 不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度

  • 继承的概念

    • 子类 拥有 父类的多有方法和属性
    • 继承描述的是类与类之间的关系
    • 好处:减少代码的冗余(相同的代码不需要多次重复书写),可以直接使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fuOpghux-1659184224042)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220724092437061.png)]

  • 语法:

    • class 类名(父类名):
    • 子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发
    • 子类中应该根据职责,封装子类特有的属性和方法
    class A(object):   # 没有写父类,但也有父类,object,object类是python中最顶级(原始)的类
    	pass
    	
    class B(A):
    	pass
    	
    # A 类,称为是 父类(基类)
    # B 类,称为是 子类(派生类)
    # 子类(B)继承父类(A)之后,子类的对象可以直接使用父类中定义的公有属性和方法
    
  • 单继承:一个类只继承一个父类,称为单继承

案例1:

# 1、定义一个动物类,吃
# 2、定义一个 狗类,继承动物类,吃,叫
# 3、定义一个 哮天犬类,继承狗类

class Animal:
    def eat(self):
        print("吃东西")

class Dog(Animal):
    def sound(self):
        print("汪汪叫...")

class XTQ(Dog):
    pass
    
A = Dog()
A.eat()
A.sound()

xtq = XTQ()
xtq.eat()  # 可以调用父类的父类的方法

运行结果:
吃东西
汪汪叫...
吃东西
  • 结论

    • python中对象.方法()调用方法
    • 先在自己的类中去找有没有这个方法,如果有,直接调用
    • 如果没有,去父类中查找,如果有,直接调用
    • 如果没有,去父类的父类中查找,如果有,直接调用
    • 如果object类中有,直接调用,如果没有,代码报错
  • 重写

    • 在子类中定义了和父类中名字相同的方法,就是重写

    • 原因:父类中的方法,不能满足子类对象的需求

    • 特点:调用子类中的方法,不再调用父类中的方法

    • 重写方式:

      • 覆盖(父类中功能完全抛弃,不要,重新书写)

        • 直接在子类中定义和父类中名字相同的方法
        • 直接在方法中书写新的代码
        class dog:
            def bark(self):
                print("汪汪叫...")
        
        class xtq(dog):
            def bark(self):
                print("嗷嗷叫...")
        
        
        xtq1 = xtq()
        xtq1.bark()
        
        运行结果:
        嗷嗷叫...
        
      • 扩展(父类中功能还调用,只是添加一些新的功能)(使用较多)

        • 直接在子类中定义和父类中名字相同的方法
        • 在合适的地方调用父类中方法 super().方法()
        • 书写添加的新功能
        class dog:
            def bark(self):
                print("汪汪叫...")
        
        class xtq(dog):
            # 1、先嗷嗷叫(新功能) 2、在汪汪叫(父类功能) 3、再嗷嗷叫
            def bark(self):
                print("嗷嗷叫...")
                super().bark()  # 调用父类中的代码
                print("嗷嗷叫...")
        
        xtq1 = xtq()
        xtq1.bark()
        
        运行结果:
        嗷嗷叫...
        汪汪叫...
        嗷嗷叫...
        

6、多态

  • 是一种写代码,调用的技巧

  • 不同的子类对象调用相同的父类方法,产生不同的执行结果

  • 多态可以增加代码的灵活度

  • 以 继承 和重写 父类方法 为前提

  • 是调用方法的技巧,不会影响到类的内部设计

  • 哪个对象调用的方法,就去自己的类中去查找这个方法,找不到去父类中找

# 1、定义 人类 person,方法work,输出:人需要工作
class person:
    def work(self):
        print("人需要工作")

# 2、定义开发工程师类coder继承person类,方法work,输出:开发的工作是写代码
class coder(person):
    def work(self):
        print("开发人员——工作是写代码")

# 3、定义 测试工程师类tester 继承person类,方法work,输出:测试的工作是测试项目...
class tester(person):
    def work(self):
        print("测试人员——工作是测试项目")

# 4、定义公司类company,定义方法show_work(查看不同岗位的工作),参数人类对象,在这个方法中调用work方法
class company:
    def show_work(self,worker):  # worker参数需要传入一个对象,只要这个对象有work方法
        worker.work()   # worker是person类以及其子类的对象
# 创建一个company类的对象
c = company()
# 创建coder类的对象
coder1 = coder()
# 创建tester类的对象
tester1 = tester()
# 创建person类对象
person1 = person()

c.show_work(coder1)
c.show_work(tester1)
c.show_work(person1)

运行结果:
开发人员——工作是写代码
测试人员——工作是测试项目
人需要工作

7、属性和方法

  • python 中一切皆对象,即使用class定义的类也是一个对象

(1)对象的划分

  • 实例对象(实例)
    • 通过 类名()创建的对象,我们称为实例对象,简称实例
    • 创建对象的过程称为是类的实例化
    • 我们平时所说的对象就是指实例对象(实例)
    • 每个实例对象,都有自己的内存空间,在自己的内存空间中保存自己的属性(实例属性)
  • 类对象(类)
    • 类对象 就是 类,或者可以认为是 类名
    • 类对象是python解释器在执行代码的过程中创建的
    • 类对象的作用:①使用类对象创建实例 类名(),②类对象 也有自己的内存空间,可以保存一些属性值信息(类属性)
    • 在一个代码中,一个类,只有一份内存空间

(2)属性的划分

  • 实例属性

    • 是实例对象具有的属性
    • 定义和使用
      • 在init方法中,使用self.属性 = 属性值定义
      • 在方法中使用self.属性名 来获取(调用)
    • 内存
      • 实例属性,在每个实例中,都存在一份
    • 使用时机
      • 基本上都是实例属性,即通过self去定义
      • 找多个对象,来判断这个值是不是都是一样的,如果都是一样的,同时变化,则一般定义为类属性,否则定义为实例属性
  • 类属性

    • 是类对象具有的属性
    • 定义和使用
      • 在类内部,方法外部,直接定义的变量,就是类属性
      • 类对象.属性名 = 属性值 or 类名.属性名 = 属性值
      • 类对象.属性名 or 类名.属性名
    • 内存
      • 只有 类对象中存在一份
  • 练习1

定义一个Dog类,定义一个类属性count,实例属性name,用来记录创建对类对象的个数,(即每创建一个对象,count的值就要加1)

class Dog:
    # 定义类属性
    count = 0

    # 定义实例属性,init方法中
    def __init__(self,name):
        self.name = name # 实例属性
        # 因为每创建一个对象,就会调用init方法,将个数加1的操作,写在init方法中
        Dog.count += 1

# 在类外部
# 打印输出目前创建几个对象
print(Dog.count)

# 创建对象
dog1 = Dog("小黄")
print(Dog.count)

dog2 = Dog("小花")
print(Dog.count)

dog3 = Dog  # 不是创建对象,个数不变
dog4 = dog1 # 不是创建对象,个数不变

# 补充,可以使用实例对象.类属性名 来获取类属性的值(原因,实例对象属性的查找顺序,先在实例属性中找,找到直接使用)
# 没有找到会去类属性中找,找到了可以使用,没有找到报错
print(dog1.count)

运行结果:
0
1
2
2

(3)方法的划分

方法,使用def关键字定义在类中的函数就是方法

  • 实例方法(常用)——self

    • 定义

      • 在类中直接定义的方法就是实例方法

        class demo:

        ​ def func(self): # 参数一般写作self,表示的是实例对象

        ​ pass

    • 使用时机

      • 如果在方法中需要使用实例属性(即需要使用self),则这个方法必须定义为实例方法
    • 调用

      • 对象.方法名() # 不需要给self传参
  • 类方法(会用)——@classmethod

    • 定义

      • 在方法名字的上方书写 @classmethod装饰器(使用@classmethod装饰的方法)

        class demo:

        ​ @classmethod

        ​ def func(cls): # 参数一般写作cls,表示的是类对象(即类名)class

        ​ pass

    • 使用时机

      • 前提,方法中不需要使用实例属性(即self)
      • 用到了类属性,可以将这个方法定义为类方法(也可以定义为实例方法)
    • 调用

      • 通过类对象调用,类名.方法名() # 也不需要给cls传参,python解释器自动传递
      • 通过实例对象调用,实例.方法名() # 也不需要给cls传参,python解释器自动传递
  • 静态方法(少用)——@staticmethod

    • 定义

      • 在方法名字的上方书写@staticmethod装饰器(使用@staticmethod装饰的方法)

        class demo:

        ​ @staticmethod

        ​ def func(): # 一般没有参数

        ​ pass

    • 使用时机

      • 前提,方法中不需要使用实例属性(即self)
      • 也不使用类属性,可以将这个方法定义为静态方法
    • 调用

      • 通过类对象调用,类名.方法名()
      • 通过实例对象调用,实例.方法名()

练习2

定义一个游戏类Game,包含玩家名字name

1、要求记录游戏的最高分top_score(类属性)

2、定义方法:show_help显示游戏的帮助信息,输出这是游戏的帮助信息

3、定义方法:show_top_score,打印输出游戏的最高分

4、定义方法:start_game,开始游戏,规则如下

​ (1)使用随机数获取本次游戏得分,范围(10-100)之间

​ (2)判断本次得分和最高分之间的关系

​ 如果本次得分比最高分高,修改最高分

​ 如果分数小于等于最高分,则不操作

​ (3)输出本次游戏得分

import random


class Game:
    top_score = 0  # 定义类属性

    def __init__(self, name):
        self.name = name  # 定义实例属性name

    @staticmethod
    def show_help():
        print("这是游戏的帮助信息")

    def start_game(self):
        print(f"{self.name}开始一局游戏")
        score = random.randint(10, 100)
        print(f"本次的游戏得分为:{score}")
        if score > Game.top_score:
            Game.top_score = score

    @staticmethod
    def show_top_score():
        print(f"游戏的最高分为:{Game.top_score}")


player1 = Game("小明")
player1.start_game()
player1.show_top_score()
player1.start_game()
player1.show_top_score()
player1.show_help()

运行结果:
小明开始一局游戏
本次的游戏得分为:88
游戏的最高分为:88
小明开始一局游戏
本次的游戏得分为:74
游戏的最高分为:88
这是游戏的帮助信息

8、哈希算法

  • 哈希(hash):是一个算法,可以对数据产生一个唯一的值(指纹)
  • is可以用来判断两个对象是不是同一个对象,即两个对象的引用是否相同
  • a is b ==> id(a) == id(b)
  • 面试题:is 和 == 的区别?
    • == 只判断数据值是否相同
    • is 判断引用是否相同

四、python文件操作

学习内容

  • 文件操作
    • 普通文件操作
    • json文件操作(重点)
  • 异常处理(程序代码运行时的报错)

1、文件的概念

(1)文件的概念和作用

  • 计算机的文件,就是存储在某种长期储存的设备上的一段数据
  • 长期存储设备包括:硬盘、U盘、移动硬盘、光盘
  • 作用:将数据长期保存下来,在需要的时候使用

(2)文件的存储方式

  • 在计算机中,文件是以二进制的方法保存在磁盘上的
  • 计算机只认识二进制(0,1)
  • 文件中存储的数据都是以二进制(0,1)的形式去存储的
  • 可以根据文件中的二进制内容,能否使用记事本软件,将其转换为文字,将文件分为两种:文本文件和二进制文件
    • 文本文件
      • 能够使用记事本软件打开(能够使用技术本转换为文字)
      • txt,md,py,html,css,js,json
    • 二进制文件
      • 不能使用记事本软件打开的
      • exe,mp3,mp4,jpg,png

2、文件操作

(1)操作步骤

  • 打开文件

    • 将文件从磁盘(硬盘)中读取到内存中
    • 语法
      • open(file,mode=‘r’,encoding=None)
      • 参数file:是要打开的文件,类型是字符串,文件的路径可以是相对路径(相当于当前代码文件所在的路径,./ …/),也可以是绝对路径(从根目录开始书写的路径),建议使用相对路径
      • 参数mode:默认参数(缺省参数),表示的是打开文件的方法
        • r:read只读打开
        • w:write只写打开
        • a:append追加打开,在文件的末尾写入内容
      • 参数encoding:编码方式,(文字和二进制如何进行转换的)
        • gbk:将一个汉字 转换为2个字节二进制
        • utf-8:常用,将一个汉字转换为3个字节的二进制
        • 返回值:返回的是文件对象,后续 对文件的操作,都需要这个对象
  • 读或者写文件

    • 写文件:向文件中写入指定的内容

      • 前提:文件的打开方式是w或者a

      • 文件对象.write(“写入文件的内容”) # 返回值:写入文件的字符数,一般不关注

      • 文件不存在,会直接创建文件

      • 文件存在,会覆盖原文件(将原文件的内容清空)

      # 1、打开文件
      f = open("a.txt","w",encoding="utf-8")
      # 2、写文件
      f.write("day day up")
      # 3、关闭文件
      f.close()
      
    • 读文件:将文件中的内容读取出来

      • 前提:文件的打开方式需要是r
      • 文件对象.read(n)
        • 参数n表示读取多少个字符,一般不写,表示读取全部内容
        • 返回值:读取到的文件内容,类型,字符串
      # 1、打开文件
      # 2、读取文件
      # 3、关闭文件
      f = open("a.txt","r",encoding = 'utf-8')
      buf = f.read()
      print(buf)
      f.close()
      
  • 关闭文件

    • 文件对象.close()
    • 将文件占用的资源进行清理,同时会保存文件,文件关闭之后,这个文件对象就不能使用了

(2)使用with open打开文件

  • with open()打开文件的好处,不用自己去书写关闭文件的代码,会自动进行关闭
  • with open(file,mode,encoding = ’utf-8‘) as 变量
  • 在缩进中去读取或者写入文件
  • 缩进中的代码执行结束,出缩进之后,文件会自动关闭
with open("a.txt","a",encoding="utf-8") as f:
    f.write("good good study")

# a方式打开文件,文件不存在会创建文件,文件存在,在文件的末尾写入内容

(3)按行读取文件内容

  • 一次读取一行内容
  • 文件对象.readline()
# with open("b.txt",encoding="utf-8") as f:
#     buf = f.readline()
#     print(buf)
#     print(f.readline())

# with open("b.txt",encoding="utf-8") as f:
#     for i in f:  # 按行读取,读到文件末尾结束
#         print(i,end="")

# read()和readline()读到文件末尾,返回一个空字符串
with open("b.txt",encoding="utf-8") as f:
    while True:
        buf = f.readline()
        if len(buf) == 0:
            break
        else:
            print(buf,end="")

# 在容器中,空容器,即容器中的数据的个数为0,表示false,其余情况都是True
with open("b.txt",encoding="utf-8") as f:
    while True:
        buf = f.readline()
        if len(buf):  # ==>if len(buf) != 0
            break
        else:
            print(buf,end="")

(4)json文件的处理

  • json是JavaScript对象表示法,是一种基于文本,独立于语言的轻量级数据交换格式

  • json文件也是一个文本文件,就可以直接使用read()和write()方法去操作文件,只是使用这两个方法,不方便,所以对json文件有自己独特的读取和写入的方法

  • 常用在 在做测试的时候,将测试数据定义为json文件格式,使用代码提取json文件,即读取测试数据,进行传参(参数化)

  • 特点

    • json是纯文本

    • json具有良好的自我描述性,便于阅读和编写

    • json具有清晰的层级结构

    • 有效地提升网络传输效率

    • 不是某种语言特有的,每种编程语言都可以使用

    • 轻量级语言,占用空间较小

    • 数据交换格式,后端程序员给前端的数据(json,html,xml)

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IvlibUFD-1659184224043)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220725151359754.png)]

(5)json语法规则

  • json文件的后缀为.json
  • json中主要数据类型为对象和数组(对象类似python的字典,数组类似python的列表),对象和数组可以互相嵌套
  • 一个json文件是一个对象或者数组(json文件的最外层要么是一个对象{},要么是一个数组[ ])
  • json中的对象是由键值对组成的,每个数据之间使用逗号隔开,但是最后一个数据后边不要写逗号
  • json中的字符串必须使用 双引号
  • json中的其他数据类型
    • 数字类型 ==》int,float
    • 字符串string ==>str
    • 布尔类型true,false ==》True,False
    • null ==>None

(6)json文件的书写

我叫小明,我今年18岁,性别男,爱好 听歌,游戏,购物,吃饭,睡觉,打豆豆

我的居住地址为 国家 中国 ,城市 上海

{
  "name":"小明",
  "age":18,
  "isMan":true,
  "like": ["听歌","游戏","购物","吃饭","睡觉","打豆豆"],
  "address": {
    "country": "中国",
    "city": "上海"
  }
}

(7)读取json文件

  • 导包 import json
  • 读打开文件
  • 读文件
    • json.load(文件对象)

返回的是字典(文件中是对象)或者列表(文件中是数组)

练习1:

[
  {
    "name": "小明",
    "age": 18,
    "isMan": true,
    "hobby": [
      "听歌",
      "游戏",
      "吃饭",
      "睡觉",
      "打豆豆"
    ],
    "address": {
      "country": "中国",
      "city": "上海"
    }
  },
  {
    "name": "小红",
    "age": 17,
    "isMan": false,
    "hobby": [
      "听歌",
      "学习",
      "购物"
    ],
    "address": {
      "country": "中国",
      "city": "北京"
    }
  }
]
import json
with open("person.json","r",encoding="utf-8") as f:
    info_list = json.load(f)
    for info in info_list:
        print(info.get("name"), info.get("age"), info.get("address").get("city"))
        
运行结果:
小明 18 上海
小红 17 北京

练习2:

[
  {
    "desc":"正确的用户名密码",
    "username": "admin",
    "password": "123456",
    "expect": "登录成功"
  },
  {
    "desc":"错误的用户名",
    "username": "root",
    "password": "123456",
    "expect": "登录失败"
  },
  {
    "desc":"错误的密码",
    "username": "admin",
    "password": "123123",
    "expect": "登录失败"
  }
     
]
import json
def read_data():
    with open("test.json","r",encoding="utf-8") as f:
        info_list = json.load(f)
        # print(info_list)
        new_list = []
        for i in info_list:  # i 为字典
            # print((i.get("username"), i.get("password"), i.get("desc"), i.get("expect")))
            new_list.append((i.get("username"), i.get("password"), i.get("desc"), i.get("expect")))

        # print(new_list)
    return new_list


print(read_data())

运行结果:
[('admin', '123456', '正确的用户名密码', '登录成功'), ('root', '123456', '错误的用户名', '登录失败'), ('admin', '123123', '错误的密码', '登录失败')]

(8)json的写入

  • 文件对象.write(字符串),不能直接将python的列表和字典作为参数传递
  • 想要将python中的数据类型存为json文件,需要使用json提供的方法,不再使用write
  • 步骤:
    • 导包import json
    • 写(w)方式打开文件
    • 写入:json.dump(python中的数据类型,文件对象)
  • 参数:
    • ensure_ascii = True/False 是否显示ascii格式
    • indent = 缩进字符数 生成文件的缩进字符数
import json
my_list = [[('admin', '123456', '正确的用户名密码', '登录成功'), ('root', '123456', '错误的用户名', '登录失败'), ('admin', '123123', '错误的密码', '登录失败')]]
with open("info4.json","w",encoding="utf-8") as f:
    # json.dump(my_list, f) # 会显示ascii码格式文字
    # json.dump(my_list,f,ensure_ascii=False)  # 直接显示中文,不以ASCII的方式显示
    # 显示缩进
    json.dump(my_list,f,ensure_ascii=False,indent=4)
[
    [
        [
            "admin",
            "123456",
            "正确的用户名密码",
            "登录成功"
        ],
        [
            "root",
            "123456",
            "错误的用户名",
            "登录失败"
        ],
        [
            "admin",
            "123123",
            "错误的密码",
            "登录失败"
        ]
    ]
]

3、异常

(1)异常概念

  • 程序在运行时,如果python解释器遇到一个错误,会停止程序的执行,并且提示一些错误信息,这就是异常
  • 程序停止执行并且提示错误信息这个动作,我们通常称之为:抛出(raise)异常

程序开发时,很难将所有的特殊情况都处理的面面俱到,通过异常捕获可以针对突发时间做集中的处理,从而保证程序的稳定性和健壮性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MSZv50mk-1659184224044)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220725203450127.png)]

(2)错误类型

(3)异常捕获(重点)

  • 程序遇到异常,默认动作是终止代码程序的执行,遇见异常之后,可以使用异常捕获,让程序代码继续运行,不会终止执行

  • 基本语法:

    try:
    	书写可能发生异常的代码
    except# 任何类型的异常都能捕获
    	发生了异常执行的代码
        
        
    try:
        书写可能发生异常的代码
    expect 异常类型:  #只能捕获指定类型的异常,如果不是这个异常,还是会报错
    	发生了异常执行的代码
        
    
# 1、获取用户从键盘输入的数据
# 2、转换数据类型为整数
# 3、输出转换之后的数据内容

try:
    num = input("请输入数字:")
    num = int(num)
    print(num)
except:
    print("请输入正确数字!")


try:
    num1 = input("请输入数字:")
    num1 = int(num1)
    print(num1)
except ValueError:   # 只能捕获ValueError类型及其子类的异常
    print("发生值异常,请重新输入正确数字!")
  • 捕获多个指定类型的异常
    • 可以针对不同的异常错误,进行单独的代码处理
try:
	书写可能发生异常的代码
except 异常类型1# 任何类型的异常都能捕获
	发生了类型1异常执行的代码
except 异常类型2:
	发生类型2异常执行的代码
...
try:
    num = input("请输入数字:")
    num = int(num)
    print(num)
    a = 10 / num   # 10 / 0
    print(f"a:{a}")

except ValueError:
    print("输入值发生了异常,请输入正确的数字...")

except ZeroDivisionError:
    print("除数不能为0")

(4)异常捕获的完整版本

  • 完整版本中内容,不是说每一次都要全部书写,根据自己的需要,去选择其中的进行使用
try:
    可能发生异常的代码
    
except 异常类型1:
	发生异常类型1执行的代码
    
# Exception是常见异常类的父类,这里书写Exception,可以捕获常见的所有异常,as常量,这个变量是一个异常类的对象,print(变量)可以打印异常信息
except Exception as 变量:
	发生其他类型的异常,执行的代码
 
else:
    没有发生异常会执行的代码
    
finally:
	不管有没有发生异常,都会执行的代码

(5)异常传递

  • 异常传递是python中已经实现好了,我们不需要操作,我们知道异常会进行传递
  • 异常传递:在函数嵌套调用的过程中,被调用的函数,发生了异常,如果没有捕获,会将这个异常向外层传递…如果传到最外层还没有捕获,才报错

五、python模块

1、模块

(1)模块的概念

模块是python程序架构的一个核心概念

  • 每一个以扩展名.py结尾的python源代码文件都是一个模块
  • 模块名同样也是一个标识符,需要符合标识符的命名规则
  • 在模块中定义的全局变量、函数、类都是提供给外界直接使用的工具
  • 模块就好比是工具包,要想使用这个工具包的工具,就需要先导入这个模块

(2)导入方式

1)import导入

import 模块名1,模块名2
模块名1.工具名  # 使用模块中的内容

示例:
import random
import json
random.randint(a,b)
json.read()
json.dump()

2)from import

from 模块名 import 工具名

工具名  #使用,如果是函数和类需要加括号

示例:
from random import randint
from json import load,dump
randint(a,b)
load()
dump()

3)from import *

将模块中所有的内容都导入

from 模块名 import *

from random import *
from json import *
randint(a,b)
load()
dump()
# 方式一
# import random
#
# print(random.randint(1, 20))

# 方式二
# from random import randint
#
# print(randint(1, 20))

# 方式三  问题:可能存在多个模块中有相同名字的工具,会冲突
from random import *

print(randint(1, 20))
  • 对于导入的模块和工具可以使用 as 关键字给其起别名
  • 如果起别名,原来的名字就不能用了,只能使用别名

(3)模块的查找顺序

在导入模块的时候,会先在当前目录中找模块,如果找到,就直接使用

如果没有找到,会去系统的目录中进行查找,找到,直接使用,没有找到,报错

注意:定义代码文件的时候,你的代码名字不能和你要导入的模块名字相同

(4)__ name __

  • 每个代码文件都是一个模块
  • 在导入模块的时候,会执行模块中的代码(三种方法都会)
  • __ name __变量:
    • 是python解释器自动维护的变量
    • 如果代码是直接运行,值是"__ main __"
    • 如果代码是被导入执行,值是模块名(即代码文件名)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I1AQK7ar-1659184224044)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220726140708334.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gRvUd842-1659184224045)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220726140748349.png)]

tools.py:

# 定义一个函数add()  对两个数字进行求和计算
def add(a,b):
    return a + b
if __name__ == '__main__':   # 该模块被调用时,下面代码不会被调用执行
    print("在代码中调用函数")
    print(add(1,2))
    print(add(10,20))
    print("该代码运行位置:",__name__)
    
运行结果:
在代码中调用函数
3
30
该代码运行位置: __main__
# 需求,调用tools模块中的add函数,进行求和计算
import tools  # 导入模块,执行tools模块中的代码

print(tools.add(100,200))

运行结果:
300

练习1:

1、定义一个模块tool.py

2、在模块中定义一个函数func,输出"我是tool模块中的func函数"

3、在模块中定义一个类Dog,具有属性name,age,方法play,输出"xx在快乐的玩耍"

4、新建一个代码文件,调用tool模块中的func函数 并创建一个Dog类的对象,调用play方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LNtEN7f9-1659184224045)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220726142939784.png)]

2、包(package)

在python中,包是一个目录,只不过在这个目录存在一个文件

__ init __.py(可以是空的)

将功能相近或者相似的代码放在一起的

在python中使用的时候,不需要可以是区分是包还是模块,使用方式是一样的

random 模块(单个代码文件)

json包(目录)

  • 语法:
import 包名

alt 回车 快捷导入


from 包名 import 类名(或方法名)

六、UnitTest框架

1、掌握UnitTest框架的基本使用方法

2、掌握断言的使用方法

3、掌握如何实现参数化

4、掌握测试报告的生成

1、介绍

  • 框架

1、框架英文单词framework

2、为解决一类事情的功能集合

  • UnitTest框架

UnitTest是python自带的一个单元测试框架,用它来做单元测试

自带的框架:不需要另外安装,只要安装了python,就可以使用

第三方框架:想要使用,需要先安装后使用(pytest)

单元测试框架:主要用来做单元测试,一般单元测试是开发做的

对于测试来说,unittest框架的作用是自动化脚本(用例代码)执行框架

(使用unittest框架来管理运行多个测试用例的)

  • 为什么使用UnitTest框架

1、能够组织多个用例去执行

2、提供丰富的断言方法(让程序代码代替人工自动的判断预期结果和实际结果是否相符)

3、能够生成测试报告

  • UnitTest核心要素(组成)

    • TestCase(最核心的模块)
      • 测试用例,注意这个测试用例是unittest框架的组成部分,不是手工和自动化中我们所说的用例(Test Case)
      • 作用:每个TestCase(测试用例)都是一个代码文件,在这个代码文件中,来书写真正的用例代码
    • TestSuite
      • 测试套件,用来管理多个TestCase的
    • TestRunner
      • 测试执行,测试运行,用来执行TestSuite的
    • TestLoader
      • 测试加载,对TestSuite功能的补充,管理,组装(打包)多个TestCase的
    • Fixture
      • 测试夹具,书写在TestCase代码中,是一个代码结构,可以在每个方法执行前后都会执行的内容

2、TestCase

1、是一个代码文件,在代码文件中,来书写真正的用例代码

2、代码文件的名字必须按照标识符的规则来书写(可以将代码的作用在文件的开头使用注释说明)

  • 步骤

    • 导包(unittest)
    • 自定义测试
      • 需要继承unittest模块中的TestCase类即可
    • 在测试类中书写测试方法
      • 书写测试方法,即用例代码,目前没有真正的用例代码,使用print代替
      • 书写要求,测试方法必须以test_开头(本质是以test开头)
    • 执行用例
      • 将光标放在类名的后边运行,会执行类中的所有的测试方法
      • 将光标放在方法名后边运行,只执行当前的方法
  • 代码

    """
    代码的目的:学习TestCase(测试用例)模块的书写方法
    """
    import unittest
    class TestDemo(unittest.TestCase):   # 需要继承unittest模块中的TestCase类即可
        #  书写测试方法,即用例代码,目前没有真正的用例代码,使用print代替
        # 书写要求,测试方法必须以test_ 开头(本质是以test开头)
        def test_method1(self):
            print("测试方法1")
    
        def test_method2(self):
            print("测试方法2")
    
    # 执行用例
    # 将光标放在类名的后边运行,会执行类中的所有的测试方法
    # 将光标放在方法名的后边运行,只执行当前的方法
    
  • 问题1:代码运行没有结果

右键运行没有unittest for …的提示,出现的问题

    • 重新新建一个代码文件,将写好的代码复制到新的代码文件中去
    • 修改已有的运行方式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dRUVU9ZT-1659184224046)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220726165120685.png)]

  • 问题2:没有找到用例

    • 测试方法中不是以test_开头的,或者单词写错了

3、TestSuite & TestRunner

  • TestSuite(测试套件):管理,打包,组装TestCase(测试用例)文件的

  • TestRunner(测试执行):执行TestSuite(套件)

  • 步骤:

    • 导包(unittest)
      • import unittest
      • from 包名 import 类名
    • 实例化(创建对象)套件对象
      • 套件对象名 = unittest.TestSuite()
    • 使用套件对象添加用例方法
      • 套件对象名.addTest(unittest.makeSuite(类名))
    • 实例化运行对象
      • 运行对象名.unittest.TextTestRunner()
    • 使用运行对象去执行套件对象
      • 运行对象名.run(套件对象名)
  • 代码:

    TestSuite(测试套件),是用来管理多个TestCase(测试用例)的,先创建多个TestCase(测试用例)文件
    

    test06_testcase:

  import unittest
  class TestDemo(unittest.TestCase):   # 需要继承unittest模块中的TestCase类即可
      #  书写测试方法,即用例代码,目前没有真正的用例代码,使用print代替
      # 书写要求,测试方法必须以test_ 开头(本质是以test开头)
      def test_method1(self):
          print("用例1测试方法1")
  
      def test_method2(self):
          print("用例1测试方法2")

​ test06_testcase1:

import unittest
class TestDemo2(unittest.TestCase):   # 需要继承unittest模块中的TestCase类即可
    #  书写测试方法,即用例代码,目前没有真正的用例代码,使用print代替
    # 书写要求,测试方法必须以test_ 开头(本质是以test开头)
    def test_method1(self):
        print("用例2测试方法1")

    def test_method2(self):
        print("用例2测试方法2")
# 1、导包
import unittest

from test06_testcase import  TestDemo
from test06_testcase1 import TestDemo2
# 2、实例化(创建对象)套件对象
suite = unittest.TestSuite()
# 3、使用套件对象添加用例方法
# 方法一,套件对象.addTest(测试类名('方法名'))   # 建议测试类名和方法名直接去复制,不要手写
# suite.addTest(TestDemo('test_method1'))
# suite.addTest(TestDemo('test_method2'))
# suite.addTest(TestDemo2('test_method1'))
# suite.addTest(TestDemo2('test_method2'))

# 方法2:将一个测试类中的所有方法进行添加
# 套件对象.addTest(unittest.makeSuite(TestDemo1))
# 缺点:makeSuite()不会提示
suite.addTest(unittest.makeSuite(TestDemo))
suite.addTest(unittest.makeSuite(TestDemo2))

# 4、实例化执行对象
runner = unittest.TextTestRunner()

# 5、使用运行对象去执行套件对象
runner.run(suite)

  运行结果:
  用例1测试方法1
  用例1测试方法2
  用例2测试方法1
  用例2测试方法2
  ....   # 运行结果中,.代表用例通过(预期结果与实际结果一致),F代表用例不通过,E代表用例代码有问题(Error)
  ----------------------------------------------------------------------
  Ran 4 tests in 0.000s

  OK

练习1:

1、在tools模块中定义add函数,对两个数字进行求和计算

2、书写TestCase代码对add()进行测试

用例1:1,2,3

用例2:10,20,30

用例3:2,3,5

import unittest
from tools import add
class TestAdd(unittest.TestCase):
    def test_method1(self):
        # 判断实际结果和预期结果是否相符
        if add(1,2) == 3:
            print("测试通过")
        else:
            print("测试不通过")
    def test_method2(self):
        # 判断实际结果和预期结果是否相符
        if add(10,20) == 30:
            print("测试通过")
        else:
            print("测试不通过")

    def test_method3(self):
        # 判断实际结果和预期结果是否相符
        if add(2,3) == 4:
            print("测试通过")
        else:
            print("测试不通过")
import unittest
from test08_test import TestAdd

suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestAdd))

runer = unittest.TextTestRunner()

runer.run(suite)

运行结果:
测试通过
测试通过
测试不通过
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

4、TestLoader(测试加载)

  • TestLoader(测试加载),作用和TestSuite的作用是一样的,对TestSuite功能的补充,用来组装测试用例的

    • 比如:如果TestCase的代码文件有很多,(10 20 ,30)

    • 使用步骤:

      • 导包
      • 实例化测试加载对象并添加用例 ==》得到的是suite对象
      • 实例化运行对象
      • 运行对象执行套件对象
    • 代码实现:

      • 对象名 = unittest.TestLoader().discover(‘用例所在的路径’,‘用例的代码文件名’)

      • 在一个项目中TestCase(测试用例)的代码,一般放在一个单独的目录(case)

      • # 1、导包
        import unittest
        # 2、实例化加载对象并添加用例
        # unittest.TestLoader().discover('用例所在的路径','用例的代码文件名')
        # 用例所在的路径,建议使用相对路径,用例的代码文件名可以使用 *(任意多个任意字符)通配符
        # suite = unittest.TestLoader().discover('./case','testcase*.py')
        # suite = unittest.TestLoader().discover('./case','*test*.py')
        suite = unittest.TestLoader().discover('./case','*test*')
        
        # 3、实例化运行对象
        # runner = unittest.TextTestRunner()
        
        # 4、执行
        # runner.run(suite)
        
        # 可以将3,4步变为一步
        unittest.TextTestRunner.run(suite)
        
      • 简化代码

        # 1、导包
        import unittest
        
        # 2、使用默认的加载对象并加载用例
        suite = unittest.defaultTestLoader.discover('case','testcase*.py')
        
        # 3、简化步骤
        unittest.TextTestRunner().run(suite)
        

5、Fixture(测试夹具)

  • Fixture(测试夹具)是一种代码结构
  • 在某些特定的情况下,会自动执行

(1)方法级别

  • 在每个测试方法(用例代码)执行前后都会自动调用的结构
# 方法执行之前
def setUp(self):
	每个测试方法执行之前都会执行
	pass
	
# 方法执行之后
def tearDown(self):
	每个测试方法执行之后都会执行
	pass

(2)类级别

  • 在每个测试类中所有方法执行前后,都会自动调用的结构(在整个类中,执行之前执行之后各一次)
# 类级别的Fixture,是一个类方法
# 类中所有方法之前
@classmethod
def setUpClass(cls):
	pass
	
# 类中所有方法之后
@classmethod
def tearDownClass(cls):
	pass

(3)模块级别

  • 模块:代码文件
  • 在每个代码文件执行前后执行的代码结构
# 模块级别的需要写在类的外边直接定义函数即可
# 代码文件之前
def setUpModule():
	pass
	
# 代码文件之后
def tearDownModule():
	pass
  • 方法级别和类级别的,前后的方法,不需要同时出现,根据用例代码的需要自行的选择使用

案例

1、打开浏览器(整个测试过程中就打开一次浏览器) 类级别

2、输入网址(每个测试方法都需要一次) 方法级别

3、输入用户名、密码、验证码、点击登录(不同的测试数据)

4、关闭当前页面(每个测试方法都需要一次) 方法级别

5、关闭浏览器(整个测试过程中就关闭一次浏览器)类级别

————————————————

1、打开浏览器(整个测试过程中就打开一次浏览器) 类级别 \ \

2、输入网址(每个测试方法都需要一次) 方法级别

3、输入用户名、密码、验证码、点击登录(不同的测试数据)

4、关闭当前页面(每个测试方法都需要一次) 方法级别

2、输入网址(每个测试方法都需要一次) 方法级别

3、输入用户名、密码、验证码、点击登录(不同的测试数据)

4、关闭当前页面(每个测试方法都需要一次) 方法级别

2、输入网址(每个测试方法都需要一次) 方法级别

3、输入用户名、密码、验证码、点击登录(不同的测试数据)

4、关闭当前页面(每个测试方法都需要一次) 方法级别

5、关闭浏览器(整个测试过程中就关闭一次浏览器)类级别 \ \

案例

import unittest
class TestLogin(unittest.TestCase):
    def setUp(self):
        """每个测试方法执行之前都会先调用的方法"""
        print("输入网址:......")

    def tearDown(self):
        """每个测试方法执行之后都会调用的方法"""
        print("关闭当前页面......")

    @classmethod
    def setUpClass(cls) -> None:
        print("——————1、打开浏览器")

    @classmethod
    def tearDownClass(cls) -> None:
        print("——————5、关闭浏览器")

    def test_1(self) -> None:
        print("输入正确用户名、密码、验证码,点击登录 1 ")

    def test_2(self) -> None:
        print("输入错误用户名、密码、验证码,点击登录 2 ")

运行结果:
Ran 2 tests in 0.002s

OK
Launching unittests with arguments python -m unittest test02-Fixture.TestLogin in C:\Users\xiaohuang\PycharmProjects\pythonProject\day10\case

——————1、打开浏览器
输入网址:......
输入正确用户名、密码、验证码,点击登录 1 
关闭当前页面......
输入网址:......
输入错误用户名、密码、验证码,点击登录 2 
关闭当前页面......
——————5、关闭浏览器

6、断言—assert

  • 让程序代替人工自动的判断预期结果和实际结果是否相符
  • 断言的结果有两种
    • True,用例通过
    • False,代码抛出异常,用例不通过
  • 为什么学习断言:
    • 提高测试效率
    • 实现自动化测试(让脚本在无人值守状态下运行)
  • 在unittest中使用断言,都需要通过self.断言方法 来试验

(1)、常用的UnitTest断言方法

序号断言方法断言描述
1assertTrue(expr,msg=None)验证expr是true,如果是false,则 fail
2aasertFalse(expr,msg=None)验证expr是false,如果是true,则fail
3assertEqual(expected,actual,msg=None)验证expected(预期结果)==actual(实际结果),不等则fail(掌握)
4assertNotEqual(first,second,msg=None)验证first != second,相等则fail
5assertIsNone(obj,msg=None)验证obj是None,不是则fail
6assertIsNotNone(obj,msg=None)验证obj不是None,是则fail
7assertIn(member,container,msg=None)验证是否member in container(掌握)
8assertNotIn(member,container,msg=None)验证是否member not in container

1)assertEqual

  • assertEqual(预期结果,实际结果)
    • 判断预期结果与实际结果是否相等
    • 如果相等,用例通过
    • 如果不相等,用例不通过,抛出异常

2)assertIn

  • assertIn(预期结果,实际结果)
    • 判断预期结果是否包含在实际结果中
    • 包含,用例通过
    • 不包含,用例不通过,抛出异常
      • assertIn(“admin”,“admin”) # 包含
      • assertIn(“admin”,“adminnnnnnnnnn”) # 包含
      • assertIn(“admin”,“aaaaaaaaaaaadmin”) # 包含
      • assertIn(“admin”,“aaaaaadminnnnnnnn”) # 包含
      • assertIn(“admin”,“addddddddmin”) # 不包含
import unittest
from tools import login

class TestLogin(unittest.TestCase):
    def test_username_password_ok(self):
        self.assertEqual('登录成功',login('admin','123456'))

    def test_username_error(self):
        self.assertEqual('登录失败',login('root','123456'))

    def test_password_error(self):
        self.assertEqual('登录失败',login('admin','123123'))

    def test_username_password_error(self):
        # self.assertEqual('登录失败',login('root','123123'))
        self.assertIn('失败',login('aaa','123123'))

7、参数化—parameterized

  • 参数化,在测试方法中,使用变量来代替具体的测试数据,然后使用传参的方法将测试数据传递给方法的变量

  • 好处:相似的代码不需要多次书写

  • 工作中场景

    • 测试数据一般放在json文件中
    • 使用代码读取json文件,提取我们想要的数据 ==》[( ),( )] or [[ ],[ ]]
  • 安装插件

    • unittest框架本身不支持参数化,想要使用参数化,需要安装插件来完成
    • 联网安装:(cmd窗口安装或者pycharm terminal安装)
      • pip install parameterized # pip是python中包(插件)的管理工具,使用这个工具下载安装插件
    • 验证:
      • pip list # 查看到parameterized
      • 新建一个python代码文件,导包验证

(1)参数化代码1

# 1、导包 unittest/parameterized
# 2、定义测试类
# 3、书写测试方法(用到的测试数据使用变量代替)
# 4、组织测试数据并传参

# 1、导包 unittest/parameterized
import unittest
from parameterized import parameterized
# 2、定义测试类
from day10.tools import login

# 组织测试数据[(),(),()]
data = [
    ('admin','123456','登录成功'),
    ('root','123456','登录失败'),
    ('admin','123123','登录失败')
]
class TestLogin(unittest.TestCase):
    # 3、书写测试方法(用到的测试数据使用变量代替)
    @parameterized.expand(data)
    def test_login(self,username,password,expect):
        self.assertEqual(expect,login(username,password))

# 4、组织测试数据并传参

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wjCFR4nd-1659184224046)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220730095610979.png)]

(2)参数化代码2

[
  {
    "desc": "正确的用户名和密码",
    "username": "admin",
    "password": "123456",
    "expect": "登录成功"
  },
  {
    "desc": "错误的用户名",
    "username": "root",
    "password": "123456",
    "expect": "登录失败"
  },
  {
    "desc": "错误的密码",
    "username": "admin",
    "password": "123123",
    "expect": "登录失败"
  }
]
# 1、导包 unittest/parameterized
import json
import unittest
from parameterized import parameterized
# 2、定义测试类
from day10.tools import login

# 组织测试数据[(),(),()]
def build_data():
    with open("data.json",'r',encoding="utf-8") as f:
        result = json.load(f)    #  [{},{},{}]
        data = []
        for i in result:
            data.append((i.get('username'),i.get('password'),i.get('expect')))
    return data

class TestLogin(unittest.TestCase):
    # 3、书写测试方法(用到的测试数据使用变量代替)
    @parameterized.expand(build_data())
    def test_login(self,username,password,expect):
        self.assertEqual(expect,login(username,password))

# 4、组织测试数据并传参

8、跳过—skip

  • 对于一些未完成的或不满足测试条件的测试函数和测试类,可以跳过执行
  • 使用方式(装饰器):
# 直接将测试函数标记成跳过
@unittest.skip('跳过的原因')

# 根据条件判断测试函数是否跳过,判断条件成立,跳过
@unittest.skipIf(判断条件,"跳过原因")
import unittest
version = 30
class TestDemo(unittest.TestCase):
    @unittest.skip("没有原因,就是不想执行")
    def test_1(self):
        print("测试方法1")

    @unittest.skipIf(version>=30,"版本大于等于30,不用测试")
    def test_2(self):
        print("测试方法2")

    def test_3(self):
        print("测试方法3")
        
运行结果:
Ran 3 tests in 0.007s

OK (skipped=2)

Skipped: 没有原因,就是不想执行

Skipped: 版本大于等于30,不用测试
测试方法3

9、测试报告

(1)Export Test Result—自带的测试报告

  • 只有单独运行TestCase的代码,才会生成测试报告

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PVZMia9C-1659184224047)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220730151719772.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gvuKRkX6-1659184224047)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220730152021248.png)]

(2)HTMLTestRunner—第三方测试报告

  • HTMLTestRunner是一个第三方的类库,用来执行测试用例并生成HTML格式的测试报告
  • 网上有多种不同的实现版本,用法都类似,只是生成的HTML报告样式有差别
  • 注意:下载的文件要与python的版本兼容

HTMLTestRuner.py:样式比较简单,不需要依赖外部JS和CSS文件

HTMLTestRunner_PY3.py:样式比较美观,需要依赖外部的JS和CSS文件

  • 使用方式
    • 获取第三方的测试运行类模块,将其放在代码的目录中
    • 导包unittest→
    • 使用套件对象,加载对象去添加用例方法
    • 实例化 第三方的运行对象 并运行套件对象
# 导包
import unittest
from HTMLTestRunner import HTMLTestRunner

# 使用套件对象,加载对象去添加用例方法
suite = unittest.defaultTestLoader.discover('case','test*.py')  # discover('.','test*.py')  '.'表示当前目录

# 实例化第三方的运行对象,并运行套件对象
# HTMLTestRunner()
# stream=sys.stdout,必填,测试报告的文件对象(open),注意点,要使用wb打开
# verbosity = 1,可选,报告的详细程度,默认 1 简略, 2 详细
# title=None,可选,测试报告的标题
# description=None,可选,描述信息,python的版本,pycharm版本

file = "report.html"  # 生成的报告文件名,报告的后缀是.html
with open(file,'wb') as f:
    # runner = HTMLTestRunner(f)    #  运行对象
    runner = HTMLTestRunner(f,2,'测试报告','python3.6.0')  # 运行对象

    # 运行对象执行套件,要写在with的缩进中
    runner.run(suite)

1、组织用例文件(TestCase里边),书写参数化,书写断言,书写Fixture,书写跳过,如果单个测试文件,直接运行,得到测试报告,如果有多个测试文件,需要组装运行生成测试报告

2、使用套件对象组装,或者使用加载对象组装

3、运行对象运行

python作业

1、描述python中变量名的命名规则

1、遵循标识符的规则(由字母、数字和下划线组成,不能以数字开头)
2、不能和系统的关键字重名
3、区分大小写
4、见名知意
5、单词之间用下划线连接

2、描述input()函数的特点?

1、input()函数用于获取键盘的输入
2、程序代码遇到input()函数,会暂停执行,等待用户输入
3、回车代表输入结束
4、输入的内容可以通过变量查看,不管输入的是什么内容,数据类型都是字符串类型

3、python中的输出函数是什么

1、输出函数为print()函数

4、按照要求完成以下代码

1、定义name、age、height变量,分别存储名字、年龄、身高信息
2、分别使用%格式化方式和f字符串方式实现
3、我的名字是xx,年龄是xx岁,身高是xx米

答案 :

name = "xiaoming"
age = 19
height = 1.70

print("我的名字是%s,年龄是%d岁,身高是%.2f米" % (name,age,height))
print(f"我的名字是{name},年龄是{age}岁,身高是{height:.2f}m")

运行结果:
我的名字是xiaoming,年龄是19岁,身高是1.70米
我的名字是xiaoming,年龄是19岁,身高是1.70m

5、从键盘获取你的用户名密码并打印

打印格式为:用户名是xxx,密码是xxx

答案:

name = input("请输入你的用户名:")
password = input("请输入密码:")

print(f"用户名是{name},密码是{password}")

运行结果:
请输入你的用户名:xiaohuang
请输入密码:123456
用户名是xiaohuang,密码是123456

6、制作一个加法计算器

用户依次输入2个整数,系统自动进行加法运算,并打印结果

答案:

num1 = input("输入的第一个数:")
num2 = input("输入的第二个数:")
# 注意输入的两个数本来是字符串类型
sum = int(num1) + int(num2)

print(sum)

运行结果:
输入的第一个数:124
输入的第二个数:3456898
3457022

7、编程题-退休年龄

用户输入年龄,如果年龄超过60岁,输出:可以退休了!否则,输出:小伙子,加油干!

age = input()
if int(age) > 60:
	print("可以退休了!")
else:
    print("小伙子,加油干!")

8、编程题-年龄阶段

用户输入年龄,按照如下标准书写程序,判断用户处于哪个年龄阶段,并提示:您的年龄是xx:青少年/青年/中年/老年

年龄阶段划分标准:0-17岁为青少年;18-35岁为青年;36-59为中年;60以上为老年

age = int(input("请输入您的年龄:"))
if 0 <= age <= 17:
    print("您的年龄是青少年!")
elif 18 <= age <= 35:
    print("您的年龄是青年!")
elif 36 <= age <= 59:
    print("您的年龄是中年!")
elif age >= 60:
    print("您的年龄是老年!")
else:
    print("输入错误!")

9、编程题-制作用户登录系统

已知A用户注册的用户名为aaa,密码是123456。具体要求如下:

登录时需要验证用户名、密码、验证码(固定验证码为qwer)

提示:系统先验证验证码是否正确,正确后在验证用户名和密码

name = input("请输入用户名:")
pwd = input("请输入密码:")
code = input("请输入验证码:")

if code == "qwer":
    if name == "aaa" and pwd == "123456":
        print("登录成功!")
    else:
        print("用户名或密码错误,请重新输入!")
else:
    print("验证码错误,请重新输入!")
    
运行结果:

请输入用户名:qwe
请输入密码:123456
请输入验证码:qwer
用户名或密码错误,请重新输入!

10、编程题-闰年判断程序

闰年是能被4整除,但不能被100整除的;或者能被400整除的年份

输入一个有效的年份,判断是不是闰年

如果是闰年,则打印xxxx年是闰年,否则打印xxxx年不是闰年

如输入2018,则打印2018不是闰年

year = int(input("请输入一个有效年份:"))
if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
    print(f"{year}年是闰年")
else:
    print(f"{year}年不是闰年")
    
运行结果:
请输入一个有效年份:2018
2018年不是闰年

11、编程题-设计计算器

请输入第一个数字:
请输入第二个数字:
请输入要进行的操作(+-*/):
计算的结果为:

示例:
请输入第一个数字:10
请输入第二个数字:20
请输入要进行的操作(+-*/):+
计算的结果为:10 + 20 = 30
num1 = int(input("请输入第一个数:"))
num2 = int(input("请输入第二个数:"))
operate = input("请输入要进行的操作:")
if operate == "+":
    print(f"计算结果为:{num1+num2}")
elif operate == "-":
    print(f"计算结果为:{num1-num2}")
elif operate == "*":
    print(f"计算结果为:{num1*num2}")
elif operate == "/":
    print(f"计算结果为:{num1/num2}")

12、编程题-猜数字游戏

1、电脑产生一个1-100的随机数,用户进行猜测(通过input输入),知道猜中为止

2、如果猜对了,输出:恭喜你猜对了,数字是xx

3、如果猜的数字比随机数大,输出:猜测的数字太大了,继续加油

4、如果猜测的数字比随机数小,输出:猜测的数字有点小,再来一次

import random

while True:
    computer = random.randint(1,100)
    user = int(input("请输入你要猜测的数字:"))
    print(f"电脑随机生成的数字:{computer}")
    if user == computer:
        print(f"恭喜你猜对了,数字是{user}")
        break
    elif user > computer:
        print("猜测的数字太大了,继续加油")
    else:
        print("猜测的数字有点小,再来一次")

13、编程题-字符串

str = "abcdefgh"
# 打印输出下标为3的字符
print("下标为3的字符:",str[3])
# 打印输出字符串中第二个字符
print("字符串中第二个字符:",str[1])
# 打印输出字符串中最后一个数据
print("字符串中最后一个字符:",str[-1])
# 打印输出字符串的长度
print("字符串的长度为:",len(str))


msg = "ABCDEFGHIJ"
#  截取下标为2 - 5(包含)字符的字符
msg1 = msg[2:6]
print(msg1)
# 截取从2到末尾的字符串
msg2 = msg[2:]
print(msg2)
# 截取从开始到5字符的字符串
msg3 = msg[:5]
print(msg3)
# 字符串逆置
msg4 = msg[::-1]
print(msg4)
str1 = "hello world and itcast and itheima and python"
# 查找字符串and的下标
num = str1.find("and",0,-1)
print(num)
# 查找字符串good的下标
num1 = str1.find("good") # 不存在则返回-1
print(num1)
# 将字符串中的and 改成 or
str2 = str1.replace("and","or",2)
print(str2)
# 按照空白字符切割,保存到变量list1中
list1 = str1.split()
print(list1)
# 使用_*_将list1中的字符串进行链接
list2 = "_*_".join(list1)
print(list2)

14、编程题—列表

# 1、定义一个列表list1
list1 = []
list1 = list()
# 2、定义一个列表list2,包含以下数据:18,“小王”,171.4,True
list2 = [18,"小王",171.4,True]
# 打印输出list2中数据的个数
print(len(list2))
# 打印输出list2中第2个数据
print(list2[1])
# 打印输出list2中最后一个数据
print(list2[-1])

15、编程题—字符串遍历

# 要求用户输入一个字符串,遍历当前字符串并打印字符,如果遇见字符”q“,则跳出循环,如果遇到空格,则跳过不输出
my_str = input("请输入一个字符串:")
for i in my_str:
    if i == "q":
        break
    if i == " ":
        continue
    print(i)

16、编程题—过7游戏

# 设计一个过7游戏,即在1-99之间的数字中,如果数字包含7或者是7的倍数,则输出”过...“,否则输出具体的数字
# 方法1:
i = 1
while i <= 99:
    if i % 7 == 0 or str(i).find("7") != -1:
        print("过")
    else:
        print(i)
    i = i +1


# 方法2:
for j in range(1,100):
    if j % 7 ==0 or str(j).find("7") != -1:
        print("过..")
    else:
        print(j)
        
# 方法3:
for j in range(1,100):
    if j % 7 ==0 or "7" in str(j):
        print("过..")
    else:
        print(j)

17、编程题—列表操作

# 有一个列表,判断列表中的每一个元素是否以s或e结尾,如果是,则将其放入一个新的列表中,最后输出这个新的列表
# list=["red","apples","orange","pink","bananas","blue","black","white"]
my_list = ["red","apples","orange","pink","bananas","blue","black","white"]
new_list = []
for i in my_list:
    if i[-1] == "s" or i[-1] == "e":
        new_list.append(i)
print(new_list)

18、编程题—随机抽签功能(提高)

# 1、使用input 输入5 个学生的名字存入列表
# 2、随机的获取一个学生的名字并打印
import random
# 定义一个列表存储所有学生信息
name_list = []
# 书写循环
for i in range(5):
    name = input("请输入名字:")
    # 将输入的名字存入到列表中
    name_list.append(name)
    # 获取一个随机下标
    num = random.randint(0,4)
print(name_list[num])

19、编程题—for循环求1-100之间数字的和

sum = 0
for i in range(1,101):
    sum = sum + i

print(sum)

20、如何向列表中添加数据

列表.append()

列表.insert(下标,数据)

列表1.extend(列表2)  ——合并列表

21、如何删除列表中的数据?

列表.pop(下标)

列表.remove(数据)

列表.clear()

22、编程题—列表操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V7KuoQUW-1659184224048)(C:/Users/xiaohuang/AppData/Roaming/Typora/typora-user-images/image-20220720225755273.png)]

my_list= ["hello","python","itcast","hello"]
# 添加数据“heima”
my_list1 = []
my_list1.extend(my_list)
my_list1.append("heima")
print(my_list1)
# 删除第一个数据
my_list2 = []
my_list2.extend(my_list)
my_list2.pop(0)
print(my_list2)
# 删除数据“hello”
my_list3 = []
my_list3.extend(my_list)
my_list3.remove("hello")
print(my_list3)
# 修改第一个数据为chuanzhi
my_list4 = []
my_list4.extend(my_list)
my_list4[0] = "chuanzhi"
print(my_list4)
#  查找chuanzhi的下标,并查找下标为2的数据
my_list5 = []
my_list5.extend(my_list4)
num = my_list5.index("chuanzhi")
str = my_list5[2]
print(num,str)
#  统计"hello"的个数
num = my_list.count("hello")
print(num)
# 统计列表中数据元素的个数(列表的长度)
num = len(my_list)
print(num)

运行结果:
['hello', 'python', 'itcast', 'hello', 'heima']
['python', 'itcast', 'hello']
['python', 'itcast', 'hello']
['chuanzhi', 'python', 'itcast', 'hello']
0 itcast
2
4

23、编程题—字典操作

  • 通过input输入3个人的信息,每个人有姓名和年龄,将信息存入字典中,并将字典存入列表

  • 遍历列表,打印每个人的信息

person_list = []
for i in range(3):
    person_name = input("姓名:")
    person_age = input("年龄:")
    my_dict = {"name":person_name,"age":person_age}
    person_list.append(my_dict)

for item in person_list:   # item是字典,因为字典存进了列表中
    print(item["name"],item["age"])
    
运行结果:
姓名:huang
年龄:1
姓名:huagn
年龄:3
姓名:jiuhs
年龄:6
huang 1
huagn 3
jiuhs 6
my_list = [{"id":1,"money":10},{"id":2,"money":20},{"id":3,"money":30},{"id":4,"money":40},]

# 定义 一个函数func,功能如下
# 1、如果字典中ID的值为奇数,则对money的值加20
# 2、如果字典中ID的值为偶数,则对money的值加10
# 3、打印输出列表,查看最终的结果

def func():
    for i in my_list:
        if i.get("id") % 2 == 1:
            i["money"] = i.get("money") + 20
        if i.get("id") % 2 == 0:
            i["money"] = i.get("money") + 10
    print(my_list)

func()

24、编程题—比较两个参数大小

定义一个函数my_max,包含两个参数,函数的作用是将两个数据中比较大的数据进行返回,如10和20 ,返回20

def my_max(num1,num2):
    if num1 > num2:
        return num1
    if num2 > num1:
        return num2
print(my_max(111,22))

运行结果:
111

25、编程题—求和函数

定义一个函数my_sum接收一个参数n,在函数中计算1+2+3+…+n的值,并在函数中打印求和结果

def my_sum(n):
    i = 1
    sum = 0
    while i <= n:
        sum = sum + i
        i = i + 1
    print(sum)
    
my_sum(10)

运行结果:
55

26、编程题—函数参数

定义一个函数func,功能如下:

1、函数存在两个参数,可以接收姓名和性别两个信息

2、调用,如果传递性别想你洗,则使用传递的数据值

3、如果不传递性别信息,性别的值为“保密”

4、在函数内部打印姓名和性别信息

def func(name,sex="保密"):
    print(f"姓名:{name},性别:{sex}")

func("xiaohuang")
func("xiuaohei","男")

运行结果:
姓名:xiaohuang,性别:保密
姓名:xiuaohei,性别:男

27、编程题—函数登录功能

定义一个函数login,函数接收两个参数,用户名username和密码password

函数功能如下:

判断输入的名字是否是admin,密码是否是123456,如果是输出 登录成功,如果不是输出 用户名或密码错误,登录失败

def login(username,password):
    if username == "admin" and password == "123456":
        print("登录成功")
    else:
        print("用户名或密码错误,登录失败")


login(username=input("请输入用户名:"),password=input("请输入密码:"))

28、编程题—任意多个数字求和

定义一个函数my_sum,函数的功能是可以对任意多个数字进行求和计算

# 方法1:
def my_sum(*args):
    num = 0
    for i in args:   # i是元组中每个数据
        num += i
    print(num)

my_sum(1,2,3,4,5,6)
my_sum(2,4,6,8,0,32)

# 方法2:
def my_sum2(*args):
    num = sum(args)
    print(num)

my_sum2(1,2,3,4,5,6)
my_sum2(2,4,6,8,0,32)

# 方法3:
def my_sum3(*args,**kwargs):
    num = 0
    for i in args:
        num += i

    for j in kwargs.values():  # 此时的kwargs为字典类型
        num += j

    print(num)
    
my_sum3(1,2,3,a=5,b=7)

运行结果:
21
52
21
52
18

29、编程题—定义一个学生类

  • 包含属性 姓名name,年龄age
  • 包含方法:
    • 吃饭的方法eat,在方法中输出xx要吃饭,xx为学生的具体名字
    • 睡觉的方法sleep,在方法中输出xx要睡觉,xx为学生具体的名字
    • 过年的方法year,要求,年龄增加一岁
  • 打印对象的时候,输出学生的姓名和年龄信息格式如下:
    • 姓名:xx,年龄:xx岁,xx为具体的名字和年龄
  • 创建两个对象,并分别调用吃饭和睡觉和过年的方法
    • 小明 18岁
    • 小红 17岁
class student:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"姓名:{self.name},年龄:{self.age}岁"

    def eat(self):
        print(f"{self.name}要吃饭")

    def sleep(self):
        print(f"{self.name}要睡觉")

    def year(self):
        self.age += 1
        print(f"过年了,今年{self.age}岁了")


student1 = student("小明",18)
student2 = student("小红",19)
print(student1)
student1.eat()
student1.sleep()
student1.year()
print(student2)
student2.eat()
student2.sleep()
student2.year()

运行结果:
姓名:小明,年龄:18岁
小明要吃饭
小明要睡觉
过年了,今年19岁了
姓名:小红,年龄:19岁
小红要吃饭
小红要睡觉
过年了,今年20岁了

30、定义一个电脑类

  • 电脑有品牌brand,有价格prince,能播放电影play_movie

  • 分别创建2个对象"小米电脑mi"和"苹果电脑mac"

  • 分别调用放电影的动作,输出内容格式如下:xx播放电影oo,xx为电脑品牌,oo为电影的名字,电影名字作为参数传递即可

    • 小米电脑播放葫芦娃
    • 苹果电脑播放变形金刚
class computer:
    def __init__(self,brand,price):
        self.brand = brand
        self.price = price

    def __str__(self):
        return f"品牌:{self.brand},价格:{self.price}"

    def play_movie(self,movie_name):
        print(f"{self.brand}播放电影{movie_name}")

mi = computer("小米电脑",4439)
print(mi)
mi.play_movie("葫芦娃")

mac = computer("苹果电脑",8999)
print(mac)
mac.play_movie("变形金刚")

31、简答题-如何读取json文件

# 1、导入json包
import json
# 2、打开文件
with open(文件名,“r”,encoding=“utf-8) as f:
	# 3、从文件中读取
	result = json.load(f)

32、编程题- 读写文件

  • 使用代码在test.txt文件中写入“wow,so beautiful"
  • 使用代码读取test.txt文件中的内容,并打印
with open("test.txt","w",encoding="utf-8") as f:
    f.write("wow,so beautiful")

with open("test.txt","r",encoding="utf-8") as f:
    print(f.read())
  • 使用代码向文件a1.txt中写入内容:张三,李四,王五,赵六
  • 使用代码读取a1.txt文件中的内容,使用字符串的方法,将每个名字存入列表my_list,打印列表
with open("a1.txt","w",encoding="utf-8") as f:
    f.write("张三,李四,王五,赵六")


with open("a1.txt","r",encoding="utf-8") as f:
    buf = f.read()
    my_list = buf.split(",")

print(my_list)

33、编程题-随机数题

按照如下要求完成代码:

1、使用随机数产生10个1-20之间的数字

2、将这些数字保存到文件data.txt中

3、读取data.txt中的内容,按照数字大小进行降序排列

4、将最大的五个数字存入文件data1.txt中

import random

with open("data.txt","w",encoding="utf-8") as f:
    for i in range(10):
        num = random.randint(1,20)
        f.write(f"{num},")


with open("data.txt",'r',encoding='utf-8') as f:
    data = f.read()  # 内容是字符串
    data = data[:-1] # 读取数据之后,最后多一个逗号,,需要去掉
    data_list = data.split(",") # 将字符串转换为列表

new_list = []
for i in data_list:
    new_list.append(int(i))

new_list.sort(reverse=True) # 对列表进行降序排序
print(new_list)
# 取前5个数据
print(new_list[:5])

34、编程题-异常捕获

1、获取用户输入的数字

2、判断获取的数字是否整数

3、如果不是整数,提示输入错误

4、如果是整数,则进一步判断是奇数还是偶数

5、最终提示:程序运行结束

def input_data():
    num = input("请输入一个数字:")
    try:
        num = int(num)

    except Exception as e:
        print("输入错误:",e)

    else:  # 没有异常则运行
        if num % 2 == 0:
            print("该数是偶数")
        else:
            print("该数是奇数")
            
    finally:  # 有无异常都运行
        print("程序运行结束")

input_data()

35、编程题-登录测试用例编写运行

tools.py

def login(username,password):
    if username == 'admin' and password == '123456':
        return '登录成功'
    else:
        return '登录失败'

testcase.py

import unittest
from tools import login

class TestLogin(unittest.TestCase):
    def test_username_password_ok(self):
        if login('admin','123456') ==  '登录成功':
            print('pass')
        else:
            print('fail')

    def test_username_error(self):
        if login('root','123456') == '登录失败':
            print('pass')
        else:
            print('fail')

    def test_password_error(self):
        if login('admin',"123123") == '登录失败':
            print('pass')
        else:
            print('fail')

    def test_username_password_error(self):
        if login('aaa','123123') == '登录失败':
            print('pass')
        else:
            print('fail')

            
运行结果:
Ran 4 tests in 0.004s

OK
Launching unittests with arguments python -m unittest 作业3.TestLogin in C:\Users\xiaohuang\PycharmProjects\pythonProject\day09


Process finished with exit code 0
pass
pass
pass
pass

在两个参数,可以接收姓名和性别两个信息

2、调用,如果传递性别想你洗,则使用传递的数据值

3、如果不传递性别信息,性别的值为“保密”

4、在函数内部打印姓名和性别信息

def func(name,sex="保密"):
    print(f"姓名:{name},性别:{sex}")

func("xiaohuang")
func("xiuaohei","男")

运行结果:
姓名:xiaohuang,性别:保密
姓名:xiuaohei,性别:男

27、编程题—函数登录功能

定义一个函数login,函数接收两个参数,用户名username和密码password

函数功能如下:

判断输入的名字是否是admin,密码是否是123456,如果是输出 登录成功,如果不是输出 用户名或密码错误,登录失败

def login(username,password):
    if username == "admin" and password == "123456":
        print("登录成功")
    else:
        print("用户名或密码错误,登录失败")


login(username=input("请输入用户名:"),password=input("请输入密码:"))

28、编程题—任意多个数字求和

定义一个函数my_sum,函数的功能是可以对任意多个数字进行求和计算

# 方法1:
def my_sum(*args):
    num = 0
    for i in args:   # i是元组中每个数据
        num += i
    print(num)

my_sum(1,2,3,4,5,6)
my_sum(2,4,6,8,0,32)

# 方法2:
def my_sum2(*args):
    num = sum(args)
    print(num)

my_sum2(1,2,3,4,5,6)
my_sum2(2,4,6,8,0,32)

# 方法3:
def my_sum3(*args,**kwargs):
    num = 0
    for i in args:
        num += i

    for j in kwargs.values():  # 此时的kwargs为字典类型
        num += j

    print(num)
    
my_sum3(1,2,3,a=5,b=7)

运行结果:
21
52
21
52
18

29、编程题—定义一个学生类

  • 包含属性 姓名name,年龄age
  • 包含方法:
    • 吃饭的方法eat,在方法中输出xx要吃饭,xx为学生的具体名字
    • 睡觉的方法sleep,在方法中输出xx要睡觉,xx为学生具体的名字
    • 过年的方法year,要求,年龄增加一岁
  • 打印对象的时候,输出学生的姓名和年龄信息格式如下:
    • 姓名:xx,年龄:xx岁,xx为具体的名字和年龄
  • 创建两个对象,并分别调用吃饭和睡觉和过年的方法
    • 小明 18岁
    • 小红 17岁
class student:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"姓名:{self.name},年龄:{self.age}岁"

    def eat(self):
        print(f"{self.name}要吃饭")

    def sleep(self):
        print(f"{self.name}要睡觉")

    def year(self):
        self.age += 1
        print(f"过年了,今年{self.age}岁了")


student1 = student("小明",18)
student2 = student("小红",19)
print(student1)
student1.eat()
student1.sleep()
student1.year()
print(student2)
student2.eat()
student2.sleep()
student2.year()

运行结果:
姓名:小明,年龄:18岁
小明要吃饭
小明要睡觉
过年了,今年19岁了
姓名:小红,年龄:19岁
小红要吃饭
小红要睡觉
过年了,今年20岁了

30、定义一个电脑类

  • 电脑有品牌brand,有价格prince,能播放电影play_movie

  • 分别创建2个对象"小米电脑mi"和"苹果电脑mac"

  • 分别调用放电影的动作,输出内容格式如下:xx播放电影oo,xx为电脑品牌,oo为电影的名字,电影名字作为参数传递即可

    • 小米电脑播放葫芦娃
    • 苹果电脑播放变形金刚
class computer:
    def __init__(self,brand,price):
        self.brand = brand
        self.price = price

    def __str__(self):
        return f"品牌:{self.brand},价格:{self.price}"

    def play_movie(self,movie_name):
        print(f"{self.brand}播放电影{movie_name}")

mi = computer("小米电脑",4439)
print(mi)
mi.play_movie("葫芦娃")

mac = computer("苹果电脑",8999)
print(mac)
mac.play_movie("变形金刚")

31、简答题-如何读取json文件

# 1、导入json包
import json
# 2、打开文件
with open(文件名,“r”,encoding=“utf-8) as f:
	# 3、从文件中读取
	result = json.load(f)

32、编程题- 读写文件

  • 使用代码在test.txt文件中写入“wow,so beautiful"
  • 使用代码读取test.txt文件中的内容,并打印
with open("test.txt","w",encoding="utf-8") as f:
    f.write("wow,so beautiful")

with open("test.txt","r",encoding="utf-8") as f:
    print(f.read())
  • 使用代码向文件a1.txt中写入内容:张三,李四,王五,赵六
  • 使用代码读取a1.txt文件中的内容,使用字符串的方法,将每个名字存入列表my_list,打印列表
with open("a1.txt","w",encoding="utf-8") as f:
    f.write("张三,李四,王五,赵六")


with open("a1.txt","r",encoding="utf-8") as f:
    buf = f.read()
    my_list = buf.split(",")

print(my_list)

33、编程题-随机数题

按照如下要求完成代码:

1、使用随机数产生10个1-20之间的数字

2、将这些数字保存到文件data.txt中

3、读取data.txt中的内容,按照数字大小进行降序排列

4、将最大的五个数字存入文件data1.txt中

import random

with open("data.txt","w",encoding="utf-8") as f:
    for i in range(10):
        num = random.randint(1,20)
        f.write(f"{num},")


with open("data.txt",'r',encoding='utf-8') as f:
    data = f.read()  # 内容是字符串
    data = data[:-1] # 读取数据之后,最后多一个逗号,,需要去掉
    data_list = data.split(",") # 将字符串转换为列表

new_list = []
for i in data_list:
    new_list.append(int(i))

new_list.sort(reverse=True) # 对列表进行降序排序
print(new_list)
# 取前5个数据
print(new_list[:5])

34、编程题-异常捕获

1、获取用户输入的数字

2、判断获取的数字是否整数

3、如果不是整数,提示输入错误

4、如果是整数,则进一步判断是奇数还是偶数

5、最终提示:程序运行结束

def input_data():
    num = input("请输入一个数字:")
    try:
        num = int(num)

    except Exception as e:
        print("输入错误:",e)

    else:  # 没有异常则运行
        if num % 2 == 0:
            print("该数是偶数")
        else:
            print("该数是奇数")
            
    finally:  # 有无异常都运行
        print("程序运行结束")

input_data()

35、编程题-登录测试用例编写运行

tools.py

def login(username,password):
    if username == 'admin' and password == '123456':
        return '登录成功'
    else:
        return '登录失败'

testcase.py

import unittest
from tools import login

class TestLogin(unittest.TestCase):
    def test_username_password_ok(self):
        if login('admin','123456') ==  '登录成功':
            print('pass')
        else:
            print('fail')

    def test_username_error(self):
        if login('root','123456') == '登录失败':
            print('pass')
        else:
            print('fail')

    def test_password_error(self):
        if login('admin',"123123") == '登录失败':
            print('pass')
        else:
            print('fail')

    def test_username_password_error(self):
        if login('aaa','123123') == '登录失败':
            print('pass')
        else:
            print('fail')

            
运行结果:
Ran 4 tests in 0.004s

OK
Launching unittests with arguments python -m unittest 作业3.TestLogin in C:\Users\xiaohuang\PycharmProjects\pythonProject\day09


Process finished with exit code 0
pass
pass
pass
pass

版权声明:本文为weixin_43936202原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。