python学习
可以用keyword中的kwlist看python中的关键字
eg:print(keyword.kwlist)
命名格式
1.见识知义
2.使用驼峰体
- 大驼峰:每个单词首字母大写,例如:MyName
- 小驼峰:第二个单词开始首字母大写,例如:myName
3.使用下划线:每个单词之间使用下划线连接,例如:my_name
代码格式要进行缩进来表示代码块:
if True:
print("true")
else:
print("true")
字符串
字符串类型:(字符串是没办法被改变的)
在字符串中单引号 ' 和双引号 " 使用完全相同
r 可以使反斜杠不发生转义,如 r"this is a line with \n"
字符串可以直接用 + 号连接
python中字符串有两种索引方式,从左到右以0开始,从右到左以-1开始。
- 如 str_a = "abc" 则str_a[0]=a ,str_a[-1]=c
Python 没有单独的字符类型,一个字符就是长度为 1 的字符串。
字符串的截取的语法格式如下:变量[头下标:尾下标:步长]
- 如str='123456789'
- print(str) # 输出字符串 print(str[0:-1]) # 输出第一个到倒数第二个的所有字符 print(str[0]) # 输出字符串第一个字符 print(str[2:5]) # 输出从第三个开始到第五个的字符 print(str[2:]) # 输出从第三个开始后的所有字符 print(str[1:5:2]) # 输出从第二个开始到第五个且每隔一个的字符(步长为2) print(str * 2) # 输出字符串两次 print(str + '你好') # 连接字符串
补充
str ="abcdefg"
print(str1[::-1]) #将字符串反转(逆置输出)
用法:
字符串.find(sub_str,start,end)
作用:在字符串中查找是否存在sub_str 这样的字符串
sub_str:要查找的小的字符串
start:开始位置,从哪个下标位置开始查找,一般不写,默认为0
end:结束位置,查找到哪个下标结束,一般不写,默认是len()
返回(代码执行之后会得到什么,如果有返回,就可以使用变量保存)
1.如果在字符串中找到了sub_str ,返回sub_str 第一次出现的下标(sub_str 中第一个字符在大字符串中的下标)
2.如果没找到,返回-1
字符串.replace(old_str,new_str,count) #将字符串中的old_str 替换为new_str
old_str:被替换的内容
new_str:替换为的内容
count:统计数据出现的次数
返回:替换之后的完成的字符串,注意:原来字符串没有发生改变
字符串.split(sep,max_split) #字符串按照sep 进行分割(拆分)
sep,字符串按照什么进行拆分,默认是空白字符(空格,换行\n,tab键\t)
max_split 分割次数,一般不写,全部分割
返回:将一个字符串拆分为多个,存到列表中
注意:如果seq不写,想要指定分割次数,则需要按照如下方式使用字符串.split(max_split=1) #n是次数
字符串.join(列表) #括号中的内容主要是列表,可以是其他内容
#作用:将字符串插入到列表中每相邻的两个数据之间,组成一个新的字符串
列表中的数据使用,用逗号隔开
注意点:列表中的数据必须都是字符串,否则会报错
字符比大小,是比较字符对应的 ASCII 码值
A<Z < a<z
ord(字符) #获取字符对应ascii的值
chr(ASCII的值)#获取对应的字符
字符串比大小:
对应下标位置字符的大小,直到比出大小,如果全部比完了,还没有比出大小,就是相等
数字类型有:
- int,通常被称为是整型或整数,是正或负整数,不带小数点。Python3 整型是没有限制大小的,可以当作 Long 类型使用,所以 Python3 没有 Python2 的 Long 类型。布尔(bool)是整型的子类型。
- bool(布尔类型)
- float(浮点数),浮点型由整数部分与小数部分组成,浮点型也可以使用科学计数法表示(2.5e2 = 2.5 x 102 = 250)
- complex(复数),复数由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示, 复数的实部a和虚部b都是浮点型。
5+4 #加法94.3 - 2 # 减法2.33 * 7 # 乘法212 / 4 # 除法,得到一个浮点数!!!0.52 // 4 # 除法,得到一个整数017 % 3 # 取余22 ** 5 # 乘方32>>> 7.0//2 #向下取整3.0
容器:
列表
List(列表类型)(List列表是可变的可以用append,pop进行添加)
- 列表是写在方括号 [ ]之间、用逗号分隔开的元素列表。
- 和字符串一样,列表同样可以被索引和截取,列表被截取后返回一个包含所需元素的新列表。
正在上传…重新上传取消
列表 list 是使用最多的一种容器(数据类型)
列表中可以存取多个数据,每个数据之间使用逗号隔开
列表中可以存放任意类型的数据
1.1定义空列表
变量 = list()
1.2 类型转换 list(容器) 讲其他的容器转换为列表
#转换字符串会将字符串中的每一个字符作为一个数据存入到列表中
在字符串中使用find方法查找下标的,不存在返回-1,
在列表中没有find方法,想要查找数据的下标,使用的是index()方法
列表.index(数据,strat,end) 使用和find方法一样,同时字符串中也有index方法
区别:返回,index()方法,找到返回第一次出现的下标,没有找到代码直接报错
尾部添加
列表.append(数据) #在数据添加到列表的尾部
指定下标位置添加
列表.insert(下标,数据) #在指定的下标位置添加数据,如果指定的下标位置本来就数据,原数据返回
列表合并
列表1.extend(列表2) #讲列表2中的所有数据逐个添加到列表1的尾部
想要修改列中指定下标位置的数据,使用的语法是:
列表[下标] = 数据
#字符串不能修改
在列表中删除中间的数据,那么后面的数据会向前移动
根据下标删除
列表.pop(下标) #删除指定下标位置对应的数据
1.下标不写,默认删除最后一个数据(常用)
2.书写存在的下标,删除对应下标位置的数据
返回:返回的删除的数据
根据数据值删除
列表.remove(数据值) #根据数据值删除
返回:none
注意:如果要删除的数据不存在,会报错
清空数据(一般不用)
列表.clear()
字符串中 反转倒置:字符串[::-1] 1.在列表当中 反转和倒置 列表[::-1] #使用切片的方法,会得到一个新列表,原列表不会发生改变 2.列表.reverse() #直接改变原列表 返回none
如果直接用 参数 = 另一个list3
则其中一个修改的话,另一个也会跟着修改
list1 =my_list[::-1]
print("my_list:",my_list)
print("list1:",list1)
#使用reverse 方法,直接改变原列表
my_list.reverse()
print("my_list",my_list)
将列表中的数据复制一份,给到一个新的列表 #使用场景:有一个列表,需要去修改操作列表中的数据,同时还要备份列表中的数据,修改之后,需要和原数据进行对比,即原数据不能改 1.使用切片 变量=列表[:] #开始到结尾 2.使用copy方法 变量 = 列表.copy()
列表推导式:快速的生成列表
变量名 = [生成数据的规则 for 变量 in xxx] #循环每执行一次,在列表中添加一个数据
列表的排序,一般来说都是对数字进行排序的 列表.sort() #按照升序排序,从小到大的排序 列表.sort(reverse=True) #降序排序,从大到小
列表可以多层嵌套
不论多少层都要可以使用下标进行访问
person_info = [["张三","18","功能测试"],["李四","20","自动化测试"]]
对于列表来说,+=的本质是extend操作
def func(list1):
list1 + =[1,2]
my_list = ['a','b']
func(my_list)
print(my_list)
最后输出为['a','b',1,2]
Tuple(元组)
- 元组(tuple)与列表类似,不同之处在于元组的元素不能修改。元组写在小括号 () 里,元素之间用逗号隔开。
- 元组中的元素类型也可以不相同:
- 元组中的数据内容不能改变,列表中的可以改变
- 元组使用( ),列表 使用[ ]
- 应用:在函数的传参或者返回值中使用,保证数据不会被改变
1.使用 类实例化的方式 2.直接使用()方式 3.特殊点,定义只有一个数据的元组时,数据后边必须有逗号 如my_tuple =(1,)
由于元组的数据不能修改,所以只能查看的方法 1.在元组中也可以使用,下标和切片获取数据 2.在元组中存在index()方法,查找下标,如果不存在,会报错 3.在元组中存在count()方法,统计数据出现的次数 4.在元组中可以使用in 操作,判断数据是否存在 5.len()统计个数 以上方法的使用,和列表中一样的
正在上传…重新上传取消
Set(集合)
- 集合(set)是由一个或数个形态各异的大小整体组成的,构成集合的事物或对象称作元素或是成员。
- 基本功能是进行成员关系测试和删除重复元素。
- 可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典
正在上传…重新上传取消
Dictionary(字典)
- 字典(dictionary)是Python中另一个非常有用的内置数据类型。
- 列表是有序的对象集合,字典是无序的对象集合。两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。
- 字典是一种映射类型,字典用 { } 标识,它是一个无序的 键(key) : 值(value) 的集合。
- 键(key)必须使用不可变类型。
- 在同一个字典中,键(key)必须是唯一的。
正在上传…重新上传取消
- 实际业务很复杂,需要用到不同类型的数据
- 不同类型数据在保存时应当加以区分
- 字典不仅可以保存多个数据,同时还能给不同数据"起名字"
- 基本结构:字典名 = {}
- 大括号内结构为: 键名 :键值 [俗称键值对]
- 多个键值对之间使用逗号隔开
1.字典dict,字典中的数据是由键(key)值(value)对组成的(键表示数据的名字),值就是具体的数据
2.在字典中一组键值对是一个数据,多个键值之间使用 逗号隔开
变量 = {key:value,key:value,...}
3.一个字典中的键是唯一的,不能重复的,值可以是任意数据
4.字典中的键 一般都是 字符串,可以是数字,不能是列表
# 1.使用 类实例化的方法
my_dict =dict()
print(type(my_dict),my_dict)
#非空字典,小明('name') 18('age') 1.71('height')True(is_men) 抽烟 喝酒 烫头('like')
my_dict2={'name':"小明","age":18,"height":1.71,"is_men":True,"like":["抽烟","喝酒","烫头"]}
print(my_dict2)
print(len(my_dict2))
my_dict2['sex'] = '男'
print(my_dict2)
#2.修改年龄为19
my_dict2['age']=19
print(my_dict2)
#3.添加一个爱好,学习--> 本质是向列表中添加一个数据
my_dict2['like'].append('学习')
字典中没有下标的概念,想要获取数据值,要使用key(键)来获取
使用 字典[键]
- 如果键存在,返回键对应的数据值
- 如果键不存在,会报错
使用 字典.get(键) 推荐使用
- 字典.get(键,数据值)
- 1.数据值一般不写,默认为none
- 返回:
- 1.如果键存在,返回键对应的数据值
- 2.如果键不存在,会报错
my_dic ={'name':'小明','age':19,'like':['抽烟','喝酒','烫头','学习']}
print(my_dic['name'])
print(my_dic.get('name'))
print(my_dic.get('name','保密')) #还是返回小明
print(my_dic.get('sex'))
print(my_dic.get('sex','保密'))
print(my_dic['like'][1])
print(my_dic.get('like')[1])
for 变量 in 字典: print(变量) #字典就是字典的key ,键 for 变量 in 字典.key(): #字典.key() 可以获取字典中所有的键 print(变量)
for 变量 in 字典.value(): #字典.values() 可以获取字典中所有的值 print(变量)
# 变量1 就是 键,变量2 就是键对应的值 for 变量1,变量2 in 字典
for 变量1,变量2 in 字典.items(): #字典.item() 获取键值对
print(变量1,变量2)
- del 字典[key] - 字典.clear() -字典.pop(key)
容器部分 总结
#1.字符串,列表,元组 支持加法运算 str1 ='hello' +'world' # 'hello world' list=[1,2] +[3,4] #[1,2,3,4] tuple1 =(1,2) +(3,4) #(1,2,3,4) #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 关键字在容器中都可以使用,注意,在字典中判断的是字典的键是否存在
函数
函数,就是把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用 函数:通俗理解,将多行代码写在一块,起个名字,在需要这多行代码的时候,可以直接使用这个名字来替代 函数的好处:减少代码的冗余(重复的代码不用多写),提高程序的编写效率
1.多行代码放在一块,起名字的过程,称为函数定义 2.函数必须先定义后调用
-
语法
def 函数名(): 函数中的代码 函数中的代码 #1.def是关键字,用来定义函数的 define的缩写 #2.函数名需要遵循标识符的规则 #3.处于def缩进中的代码,称为函数体 #4.函数定义的时候,函数体中的代码不会执行,在调用的时候执行
-
函数定义小技巧:
-
在前期,书写不熟练的时候, 1.可以先不管函数,先把功能写出来, 2.给多行代码起名字 3.选中多行代码,使用tab 键进行缩进
1.使用多行代码的时候,成为函数调用
-
语法
-
函数名() #1.函数调用的时候会执行函数体中的代码 #2.函数调用的代码,要写在函数体外边
在一个函数定义调用另一个函数 1.函数定义不会执行函数体中的代码 2.函数调用会执行函数中的代码 3.函数体中代码结束会回到函数被调用的地方继续向下执行
函数的返回值,可以理解为是 整个函数整体执行的结果是什么 什么上班需要书写返回值:函数中得到的数据在后续的代码中还要使用,这个时候就应该将这个数据作为返回值返回,以供后续使用 print() input() type() len() 在函数中想要将一个数据作为返回值 返回,需要使用return 关键字(只能在函数中使用) 作用: 1.将数据值作为返回值返回 2.函数代码执行遇到return,结束函数执行
获取用户使用键盘录入的内容
使用的函数 input()
变量 = input("提示的信息")
变量为字符串类型
1.代码从上到下执行,遇到input函数,会暂停执行,等待用户输入
输出使用的函数是 print()函数,作用,将程序中的数据或者结果打印到控制台(屏幕)
pirnt('hello world')
name ='小明'
print(name)
print(name,age) #可以使用逗号输出多个内容
在字符串中指定的位置,输出变量中存储的值
1.在需要使用变量的地方,使用特殊符号占位
2.使用变量填充占位的数据
%格式化输出占位符号
- %d 占位,填充 整形数据 digit
- %f 占位,填充 浮点型数据 float
- %s 占位,填充 字符串类型 string
name ="Sum"
age =18
height =171.1
print("我的名字是%s 年龄是%d 身高是%.2f" %(name,age,height))
# 小数默认显示6位,如果想要指定显示小数点后几位,%.nf ,n需要换成具体的整数数字,即保留小数的位置
#补充
stu_num =1
print("我的学号为%d" % stu_num)
# %0nd n需要换成具体的整数数字,表示整数一共占几位
print("我的学号是%06d" %stu_num)
字符串.format()
字符串.fomat() 可以再任意版本中使用
1.在需要使用 变量的地方使用 {}占位
2."{} ,{},...".format(变量,变量,...)
eg:print("我的名字是{},年龄是{},身高是{}m,学号是{},本次考试的及格率为{}%").foemat(name,age,height,stu_id,pasr)
f"{变量}" F"{变量}"
name ="Sum"
age =18
height =171.1
print(f"我的名字是{name} 年龄是{age} 身高是{height}")
添加引号括号:可以直接选中要添加引号或者括号的内容,书写即可 删除一行:ctrl x 复制粘贴一行:ctrl d 新建一行,在代码下面,新建一行: shift 回车 快速注释 选中并且按 ctrl + /
type(变量) 可以获取变量的数据类型
文档注释的本质,还是注释,只不过书写的位置和作用比较特殊 1.书写的位置,在函数名的下方使用,三队双引号进行注释 2.作用:告诉别人这个函数如何使用 3.查看,在调用的时候,将光标放在函数名上,使用快捷键 Ctrl q
函数进阶
函数中想要返回一个数据值,使用 return 关键字 将多个数据值组成容器进行返回,一般是元组(组包)
def calc(a,b)
num = a + b
num1 = a - b
return num,num1
#写法一
result =calc(10,5)
print(result,result[0],result[1])
#直接拆包
x,y =calc(20,10)
print(x,y)
形参的不同书写方法
位置传参 - 在函数调用的时候,按照形参的顺序,将实参值传递到形参 关键字传参 - 在函数调用的时候,指定数据值给到那个参数
缺省参数,默认参数 列表.pop() #不写参数,删除最后一个 列表.sort(reverse = True) 1.定义方式 在函数定义的时候,给形参一个默认的数值,这个形参就变成缺省参数,注意缺省参数的书写放在普通参数的后面 2.特点(好处) 缺省参数,在函数调用的时候,可以传递实参值,也可以不传递实参值 如果传参,使用的就是传递的实参值,如果不传参,使用的就是默认值
def show_info(name,sex='保密')
print(name,sex)
show_info('小王')
show_info('小王','男')
print(1) print(1,2,3) print(1,2,3,4) print函数 sep=' '每个位置参数之间的间隔 end='\n' print所有参数输出之后,会再次输出end end = ' '连接下一句输出语句
当我们在书写函数的时候,不确定参数的具体个数的时候,可以使用不定长参数 *args是元组 **kwargs是字典
def 函数名(普通参数,*args,缺省参数,**kwargs)
pass
def func(*args,**kwargs):
print(type(args),args)
print(type(kwargs),kwargs)
print('_'*30)
func()
func(1,2,3) #位置传参,数据都给了args
func(a=1,b=2,c=3)#关键字传参,数据都给了kwargs
匿名函数
匿名函数:就是使用 lamda 关键字定义的函数 一般称为 def 关键字定义的函数为,标准函数 匿名函数只能书写一行代码 匿名函数的返回值不需要 return,一行代码(表达式)的结果就是返回值 语法: lambda 参数:一行代码
-
语法
-
lamba 参数:一行代码 #匿名函数一般不需要我们主动去调用,一般作为函数的参数使用的 func11 =lambda a,b:a*b print(func11(1,2))
-
匿名函数作为函数的参数 - 列表中的字典排序
user_list = [{"name":"zhangsan","age":18},{"name":"lisi","age":19},{"name":"wangwu","age":17}] 列表排序(列表中的数字): 列表.sort() 列表.sort(reverse =True) 列表中的内容都是字典,想要排序 列表.sort(key=lambda x:x['键'])
类型转换
根据代码的需要,将一种数据类型转换成另一种数据类型(将input输入得到的数字转换为整型)
如 变量 = int(变量) 还有float(), str()
循环语句
for循环可以遍历容器中的数据(
遍历:从容器中把数据一个一个拿出来
容器:可以简单理解为盒子,盒子中可以存放很多的数据(字符串 str ,列表 list ,元组 tuple ,字典 dict))
for 循环 也可以称为for遍历
语法:
for 变量名 in 容器
重复执行的代码
#1.for 和 in 都是关键字
#2.容器中有多少个数据,循环会执行多少次(0 个数据 ,执行0次)
#3.每次循环,会讲容器中数据取出来一个保存到in 关键字前面的变量中
for i in range(101): #只能执行到100 跟索引一样遵循左闭右开
print(i)
for i in range(2,101,2): #从2到100 间隔为2取数
print(i)
#if语句
#补充not in
if i not in range(2):
print(i)
a = "Hello"
b = "Python"
print("a + b 输出结果:", a + b)
print("a * 2 输出结果:", a * 2)
print("a[1] 输出结果:", a[1])
print("a[1:4] 输出结果:", a[1:4])
if( "H" in a) :
print("H 在变量 a 中")
else :
print("H 不在变量 a 中")
if( "M" not in a) :
print("M 不在变量 a 中")
else :
print("M 在变量 a 中")
my_str ="hello"
for i in my_str:
print("!!!!")
break 和 continue 是python中的两个关键字,只能在循环中使用 break:终止循环,即代码执行遇到break,循环不再执行,立即结束 continue,跳过本次循环,即代码执行遇到continue,本次循环剩下的代码跳过
while i<=100:
print(i)
i++
列表去重
列表去重:列表中存在多个数据,需要,去除列表中的重复的数据 方式1.遍历
list =[1,2,3,4,5,5,6,4]
list2 = []
list2.append(list[0])
for i in list:
if i in list2:
continue
else:list2.append(i)
print(list2)
方式2 在python中用一种数据类型(集合) set 特点:集合中不能有重复的数据(如果有重复的数据会自动去重) 可以使用集合的特点对列表进行去重 1.使用set() 类型转换将列表转换为集合类型 2.再使用list()类型转换成集合 转换为列表 缺点:不能保证数据在原列表中出现的顺序(一般来说,也不需要考虑)
变量进阶
可变类型和不可变类型
数据类型:int float bool str list tuple dict set 可变不可变是指:数据所在的内容是否允许修改,允许修改就是可变类型,不允许修改就是不可变类型 可变类型:列表 list 字典 dict 集合 set 列表.append() 字典.pop(键) 不可变类型:int float bool str tuple
Python 交换两个变量的值和拆包
#python特有的 a,b = b,a print(a,b)
组包(pack):将多个数据值使用逗号连接,组成元组 拆包(unpack):将容器的数据值使用多个变量分别保存的过程,注意:变量的个数和容器中的个数要保持一致 赋值运算符,都是先执行等号右边的代码,执行的结果,保存到等号左边的变量中 将列表或者元组中的数据作为位置参数进行传递 *列表或者*元组 将字典中的数据作为关键字参数进行传递 **字典
局部变量和全局变量
变量:根据变量的定义位置,可以将变量分为局部变量和全局变量
局部变量:在函数内部(函数的缩进中)定义的变量,称为局部变量 特点: 1.局部变量只能在当前函数内部使用,不能在其他函数和函数外部使用 2.在不同函数中,可以定义名字相同的局部变量,两者之间没有影响 3.生命周期 在函数被调用的时候,局部变量被创建,函数调用结束,局部变量的值被销毁(删除),不能使用 所以函数中的局部变量的值,如果想要在函数外部使用,需要使用return关键字,将这个值进行返回
定义位置:在函数外部定义的变量,称为是全局变量 特点: 1.可以在任何函数中读取(获取) 全局变量的值 2.如何在函数中存在和全局变量名字相同的局部变量,在函数中使用的是 局部变量的值(就近) 3.函数内部想要修改全局变量的引用,需要添加global关键字,对变量进行声明为全部变量 4.生命周期 代码执行时候被创建,代码执行结束,被销毁(删除)
面向对象
面向对象是一种编程思路(写代码的套路) 编程思想: 1.面向过程 2.面向对象 以上两种都是属于写代码的套路(方法),最终目的都是为了将代码写出来,只不过过程和思考方法不太一样
面向对象的核心思想是 找一个对象去帮我们处理事情 在程序代码中 对象是由 类 创建的 类和对象,是 面向对象编程思想中非常重要的两个概念
- 类
- 对象
1.类名(给这多个事物起一个名字,在代码中 满足大驼峰命名法(每个单词的首字母大写)) 2.属性(事物的特征,即有什么,一般文字中的名词) 3.方法(事物的行为,即做什么事,一般是动词)
类的抽象
类的抽象,其实就是找到 类的 类名 ,属性 和方法
先定义简单的类,不包含属性,在python中定义类需要使用关键字 方法:方法的本质是在类中定义函数,只不过,第一个参数是:self
class 类名: def 方法名(self): #这就是一个方法
创建对象是使用 类名() 进行创建 ,即
类名() #创建一个对象,这个对象在后续不能使用
#创建的对象想要在后续的代码中继续使用,需要使用一个变量,将这个对象保存起来
变量 = 类名()
#一个类可以创建多个对象,只要出现 类名() 就是创建一个对象,每个对象的地址是不一样的
class 类名:
def 方法名(self):
pass
变量 = 类名()
对象.方法名()
需求:小猫爱吃鱼,小猫要喝水 类型:猫类 Cat 属性:暂无 方法:吃鱼(eat) 喝水(drink)
class cat:
def eat(self):#self会自动出现,暂不管
print('小猫爱吃鱼')
def drink(self):
print('小猫要喝水')
cat().eat()
class cat:
def eat(self):#self会自动出现,暂不管
print('小猫爱吃鱼')
def drink(self):
print('小猫要喝水')
cat().eat()
1.从函数语法上说,self是形参,就可以是任意的变量名,只不过我们习惯将这个形参写出self
2.self是普通的形参,但在调用的时候没有传递实参数,原因是,python解释器在执行代码的时候,自动的将调用这个方法的对象,传递给了self,即self的本质是对象
3.验证,只需要确定,通过哪个对象调用,对象的引用和self的引用是一样的
4.self 是函数中的局部变量,直接创建对象是全局变量
5.self只能在方法内部使用,不能在方法外使用
对象.属性名 = 属性值
-
类内部进行添加
-
在内部方法中,self是对象, self.属性名 = 属性值 #在类中添加属性一般写在 _init_方法中
-
类外部添加
-
对象.属性名 = 属性值 #一般不使用
对象.属性名
-类内部
在内部方法中,self是对象, self.属性名
-类外部
对象.属性名 #一般很少用
魔法方法
python 中有一类方法,以两个下划线开头,两个下划线结尾,并且在满足某个条件的情况下,会自动调用,这个方法称为 魔法方法 学习: 1.什么情况下自动调用 2.有什么用,用在哪 3.书写的注意事项
1.什么情况下自动调用 创建对象之后会自动调用 2.有什么用,用在哪 给对象添加属性的,(初始化方法,构造方法) 2.某些代码,在每次创建对象之后,都要执行,就可以将这行代码写在__init__方法中 3.书写的注意属性 1.不要写错了 2.如果init方法中,存在出现了 self 之外的参数 ,在创建对象的时候必须传参
1.什么情况下自动调用 使用print(对象) 打印对象的时候,会自动调用 2.有什么用,用在哪 在这个方法中一般书写对象的属性信息的,即打印对象的时候想要查看什么信息,在这个方法中进行定义 如果类中没有定义__str__方法,print(对象),默认输出对象的引用地址 3.书写的注意属性 这个方法必须返回!!!! 一个字符串
class Cat:
"""
猫类,属性name,age,show_info(输出属性信息)
"""
# 定义添加属性
def __init__(self, name,age): # 创建对象之后,输出
self.name = name # 添加属性 name
self.age = age # 添加age属性
def show_info(self):
print(f'小猫的名字是{self.name},年龄是;{self.age}')
def __str__(self):
# 方法必须返回一个字符串,只要是个字符串就行
return f'小猫的名字是{self.name},年龄是;{self.age}'
blue_cat = Cat('蓝猫',22) # 创建对象,会输出
print(blue_cat)
blue = blue_cat.show_info() # 不是创建对象
__init__方法,创建对象之后,会自动调用 __del__方法,对象被删除销毁时,自动调用的(遗言,处理后事) 1.调用场景,程序代码运行结束之后,所有对象都被销毁 2.调用场景,直接使用del 删除对象(如果对象有多个名字(多个对象引用一个对象),需要吧所有有的对象都删除才行)
实例
1.
class Person:
def __init__(self,name,weight):
self.name =name
self.weight = weight
def __str__(self):
return f'姓名:{self.name},体重:{self.weight}kg'
def run(self):
print(f'{self.name} 运动了,体重减少了')
#减体重,即修改属性
self.weight -=0.5
def eat(self):
print(f'{self.name} 大餐一顿,体重增加了')
#修改体重
self.weight +=1
xm = Person('小明',75.0)
print(xm)
xm.run()
print(xm)
xm.eat()
print(xm)
正在上传…重新上传取消
class HouseItem:
"""家具类"""
def __init__(self,name,area):
"""添加方法"""
self.name = name
self.area = area
def __str__(self):
return f'家具名字{self.name},占地面积 {self.area} 平米'
class House:
"""房子类"""
def __init__(self,name,area):
self.name =name #户型
self.total_area =area #总面积
self.free_area =area #剩余面积
self.item_list =[] #家具名称列表
def __str__(self):
return f"户型:{self.name},总面积:{self.total_area}平米,剩余面积:{self.free_area} 平米 " \
f"家具名称列表:{self.item_list}"
def add_item(self,item): #item表示家具对象
# 判断房子剩余面积(self.free_area)和家具的占地面积(item.area)之间的关系
# self表示 房子对象 缺少一个家具对象
if self.free_area >= item.area:
#添加教具
self.item_list.append(item.name)
#修改剩余面积
self.free_area -=item.area
print(f'{item.name}添加成功')
else:print('修改失败')
bed = HouseItem('席子',4)
chest = HouseItem('餐桌',2)
table = HouseItem('餐桌',1.5)
#创建房子对象
house = House('三室一厅',150)
print(house)
#添加 床
house.add_item(bed)
print(house)
正在上传…重新上传取消
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}')
login = LoginPage('admin','123456','8888')
login.login()
私有和公有
1.在python中定义的方法和属性,可以添加访问控制权限(即在什么地方可以使用这个属性和方法) 2.访问控制权限分为两种,公有权限,私有权限 3.公有权限 直接书写的方法和属性,都是公有 公有的方法和属性,可以在任意的地方访问和使用 4.私有权限 在类内部,属性名或者方法名 前面加两个 下划线,这个属性或者方法 就变成 私有的 私有的方法和属性,只能在当前类的内部使用 5.什么时候定义私有 1.某个属性或者方法,不想在类外部访问和使用,就将他定义为私有即可 2.测试中,一般不怎么使用,直接公有即可 3.开发中,会根据需求文档,确定什么作为私有 6.如果想要在外部操作私有属性,方法是,在类内部定义共有的方法,我们通过这个方法进行操作
定义一个Person类,属性name,age(私有)
class Person:
def __init__(self,name,age):
self.name = name
# 私有的本质,是python 解释器执行代码的时候发现属性名或者方法名前有两个_,会将这个名字重命名
# 会在这个名字前边加上,_类名前缀,即self.__age ===> self._Person__age
self.__age = age #年龄,将其定为私有,不能在外部修改
def __str__(self):
return f'名字{self.name},年龄{self.__age}'
xm = Person('小明',18)
# 在类外部直接访问age属性
# 直接修改 age 属性
xm.age = 20
#print(xm.__age) 不能在类外部进行使用
xm.__age =20 #这个不是修改私有属性,而是添加了一个公有属性__age
print(xm.age)
# 对象.__dict__ 魔法属性,可以将对象具有的属性组成字典返回
继承
- 封装 根据 职责 将属性 和 方法 封装 到一个抽象的 类 中
- 继承 实现代码的重用,相同的代码不需要重复的编写
- 多态 不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度
继承的概念:子类 拥有 父类 的所有 方法 和 属性
class A(object) class A: #没有去写父类,但也有父类,object,object 类 是Python 中最顶级*原始的类 pass class B(A): pass 1.A 类,称为是 父类(基类) 2.B类,称为是 子类(派生类) 单继承:一个类只继承一个父类,称为单继承 继承之后的特点: 子类(B)继承父类(A)之后,子类的对象可以直接使用父类中定义的公有属性和方法
-
案例
1.定义一个 动物类 吃 2.定义一个 狗类 继承动物类,吃,叫 3.定义一个 哮天犬类,继承 狗类
""" 1.定义一个 动物类 吃 2.定义一个 狗类 继承动物类,吃,叫 3.定义一个 哮天犬类,继承 狗类 """ class Animal: def eat(self): print('要吃东西') class Dog(Animal): def bark(self): print('汪汪汪') class XTQ(Dog): pass ani = Animal() ani.eat() dog = Dog() dog.eat() dog.bark() xtq = XTQ() xtq.eat()
python 中 对象.方法() 调用方法 1.现在自己的类中的去找有没有这个方法 如果有,直接调用 2.如果没有去父类中 查找,如果有,直接调用 3.如果没有,去父类的父类中查找,如果有直接调用 4.... 5.如果object 类中有,直接调用,如果没有,代码报错
重写
重写:在子类中定义了和父类中名字相同的方法,就是重写 重写的原因:父类中的方法,不能满足子类对象的需求,所以重写 重写之后的特点:调用子类字节的方法,不再调用父类中的方法 重写的方式: 1.覆盖(父类中功能完全抛弃,不要,重写书写) 2.扩展(父类中功能还调用,只是添加一些新的功能)(使用较多)
覆盖
1.直接在子类中,定义和父类中名字相同的方法 2.直接在方法中书写新的代码
class Dog:
def bark(self):
print('汪汪汪叫....')
class Xitiao(Dog):
# 重写bark方法
def bark(self):
print('嗷嗷嗷叫')
xtq = Xitiao()
xtq.bark()
扩展父类中的功能
1.直接在子类中,定义和父类中名字相同的方法 2.在合适的地方调用 父类中方法 super().方法() 3.书写添加的新功能
class Dog:
def bark(self):
print('汪汪汪叫....')
class Xitiao(Dog):
# 重写bark方法
# 1.先 嗷嗷嗷叫(新功能) 2,汪汪汪叫(父类中功能) 3.嗷嗷嗷叫(新功能)
def bark(self):
print('嗷嗷嗷叫')
super().bark() #print() 如果父类中代码有多行呢
print('嗷嗷嗷叫...')
xtq = Xitiao()
xtq.bark()
多态
1.是一种写代码,调用的一种技巧 2.同一个方法,传入不同的对象,执行得到不同的结果,这种现象称为多态 3.是调用方法的技巧,不会影响到类的内部设计 哪个对象调用方法,就去自己的类中去查找这个方法,找不到去父类中找
属性和方法
Python中一切皆为对象 即 使用class 定义的类 也是一种对象
对象的划分
1.通过 类名() 创建的对象,我们称为实例对象,简称实例 2.创建对象的过程称为类的实例化 3.我们平时所说的对象就是指实例对象(实例) 4.每个实例对象,都有自己的内存空间,在自己的内存空间中保存自己的属性(实例属性)
1.类对象 就是 类,或者可以认为是 类名 2.类对象是Python解释器在执行代码的过程中 创建的 3.类对象的作用:使用类对象创建实例 类名(),第二个作用 类对象 也有自己的内存空间,可以保存一些属性值信息(类属性) 4.在一个代码中,一个类 只有一份内存空间
属性的划分
-
是实例对象具有的属性
-
定义和使用
在__init__方法中,使用self.属性名 = 属性值 定义 在方法中是 使用self.属性名 来获取(调用)
-
内存
实例属性,在每个实例中 都存在一份
-
使用时机
1.基本上 99% 都是实例属性,即通过self 去定义 2.找多个对象,来判断这个值是不是都是一样的,如果都是一样,同时变化,则一般定义为类属性,否则定义为 实例属性
-
是 类对象 具有的属性
-
定义和使用
在类内部,方法外部,直接定义的变量,就是类属性 class Game: #类属性,游戏的最高分 top_score = 0 这就是一个类属性 def __init__(self,name): # 定义实例属性 self.name = name 使用:类对象.属性值 = 属性值 or 类名.属性值 = 属性值 类对象.属性名 or 类名.属性名 -
内存
只有 类对象 中存在一份
-
定义
# 在类中直接定义的方法 就是 实例方法 class Demo: def func(self): #参数一般写作 self,表示的是实例对象 pass
-
定义的时机(什么时候用)
如果在方法中需要使用实例属性(即需要使用self),则这个方法定义为 实例方法
-
调用
对象.方法名() #不需要给 self 传参
-
定义
#在方法名字的上方书写 @classmethod 装饰器(使用@classmethod 装饰的方法) class Demo: @classmethod def func(cls): # 参数一般写作 cls,表示的类对象(即类名) class pass -
定义时机(什么时候用)
1.前提,方法中不需要使用 实例属性(即self) 2.用到了类属性,可以将这个方法定义为类方法,(也可定位为实例方法)
-
调用
1.通过类对象调用 类名.方法名() #也不需要给cls传参,python解释器自动传递 2.通过实例对象调用 实例.方法名() #也不需要给cls传参,python解释器自动传递
-
定义
# 在方法名字的上方书写 @statimethod 装饰器(使用 @staticmethod 装饰的方法) class Demo: @staticmethod def func(): #一般没有参数 pass
-
定义时机(什么时候用)
1.前提,方法中不需要使用 实例属性(即self) 2.也不使用 类属性,可以将这个方法定义为 静态方法
-
调用
1.通过类对象调用 类名.方法名() 2.通过实例对象调用 实例.方法名()
-
优化(使用 类方法 和静态方法)
@staticmethod def show_help(): print('help') @classmethod def show_top_score(cls): print(f'游戏的最高分为{Game.top_score}')
哈希
哈希(hash):是一个算法, 可以对数据产生一个唯一的值(指纹) is 可以用来判断两个对象是不是同一个对象,即 两个对象的引用是否相同 a is b ====> id(a) == id(b) 面试中可能会问: is 和 == 区别? == 只判断数据值是否相同,is 判断引用是否相同
文件
文件介绍
计算机的 文件,就是存储在某种 长期存储设备 上的一段 数据 作用:将数据长期保存下来,在需要的时候使用 1.计算机只认识 二进制(0,1) 2.文件中存储的数据都是以二进制(0 1)的形式去存储的 可以根据 文件中的二进制内容,能否使用记事本软件,将其转换为文字,将文件分为两种:文本文件和二进制文件
-
文本文件
- 能够使用记事本软件打开(能够使用记事本转换为文字)
- txt ,md ,py ,html ,css , js ,json
-
二进制文件
- 不能使用记事本软件打开的,
- exe,mp3,mp4,jpg,png
文件操作
1.打开文件 2.读或者写文件 3.关闭文件
打开文件:将文件从磁盘中(硬盘) 中 读取到内存中 语法: open(file,mode='r',encoding =None) 参数file:要打开的文件,类型是字符串,文件的路径可以是相对路径可以相对路径,也可以是绝对路径(从根目录开始书写的路径)。建议使用相对路径(相对于当前代码文件所在的路径,./ ../) 参数 mode:默认参数(缺省参数),表示的是打开文件的方式, r:read 只读打开 w:write 只写打开 a:append 追加打开,在文件的末尾写入内容 参数 encoding:编码打开,(文件和二进制如何进行转换的) gbk:将一个汉字转换为 2个字节二进制 utf-8:常用,将一个汉字转化为3个字节的二进制 返回值:返回的是 文件对象 ,后续对文件的操作,都需要这个对象
向文件中写入指定的内容 前提:文件的打开方式是w 或者 a(在文件末尾进行写入内容) 文件对象.close()
文件对象.write('写入文件的内容')
#注意:
1.文件不存在,会直接创建文件
2.文件存在,会覆盖原文件(将原文件中的内容清空)
# 返回值:写入文件的字符数,一般不关注
#1.打开文件
f = open('a.txt','w',encoding='utf-8')
#2.写文件
f.write('好好谢谢\n')
f.write('好好学习')
#3.关闭文件
f.close()
将文件中的内容读取出来 前提:文件的打开方式需要是 r 文件对象.read(n) #参数 n 表示读取多少个字符,一般不写,表示读取全部内容 #返回值:读取到的文件内容,类型: 字符串
#1.打开文件
f = open('a.txt','r',encoding='utf-8')
#2.读文件
buf = f.read()
print(buf)
#3.关闭文件
f.close()
# r 方式打开文件,如果文件不存在,代码会报错
关闭文件:将文件占用的资源进行清理,同时会保存文件,文件关闭之后,这个文件对象就不能使用了 文件对象.close()
with open() 打开文件的好处:不用自己去书写关闭文件的代码,会自动进行关闭
with open(file,'r',encoding='utf-8') as 变量:
#在缩进中读取或者写入文件
#缩进中的代码执行结束,出缩进之后,文件会自动关闭
按行读取文件:一行读取一行内容 文件对象.readline()
with open('a.txt','r',encoding='utf-8') as f:
buf = f.readline()
print(buf)
print(f.readline())
with open('a.txt','r',encoding='utf-8') as f:
for i in f:
print(i,end='')
with open('b.txt',encoding='utf-8') as f:
while True:
buf = f.readline()
if len(buf) == 0
break
else:
print(buf,end='')
JSON操作
json文件 也是一种文本文件,就可以直接使用 read() 和 write() 去操作文件,只是使用这两个方法,不方便,所以对json文件有自己独特的读取和写入的方法 常用在 做测试的时候,将测试数据定义为 json 文件格式,使用 代码读取 json 文件,即读取测试数据,进行传参(参数化)
基于文本,独立于语言的轻量级的数据交换格式 - 基于文件,是一个文本文件,不能包含图片,音视频等 - 独立于语言,不是某一个语言特有的,每种编程语言都可以使用的 - 轻量级,相同的数据,和其他格式相比,占用的大小比较小 - 数据交换格式,后端程序员 给前端的数据(json,html xml)
1.json 文件的后缀是 .json
2.json 中主要的数据类型为 对象({} 类似 python中 字典) 和 数组([],类似python中的列表),对象和 数组可以互嵌套
3.一个json文件是一个 对象或者数组(即 json 文件的最外层要么是一个{},要么是一个数组 [])
4.json 中的对象是由键值对组成的,每个数据之间使用 逗号隔开,但是最后一个数据后边不要写逗号
5.json中的字符串 必须使用 双引号""
6.json中的其他数据类型
数字类型 int float
string字符串 str
布尔类型 true false ------ True False
null ---------None
我叫小明,我今年 18 岁,性别男,爱好 听歌,游戏,购物,吃饭,睡觉,打豆豆 我的居住地址为 国家中国,城市上海
{
"name": "小明",
"age": 18,
"Sex": "男",
"like": [
"听歌",
"游戏",
"动物",
"吃饭",
"打豆豆"
],
"adress": {
"country": "中国",
"city": "上海"
}
}
1.导包 import json 2.读打开文件 3.读文件 json.load(文件对象) #返回的是 字典(文件中是对象)或者是列表(文件中是数组)
#1.导入json
import json
#2.读取打开文件
with open('info.json','r',encoding='utf-8') as f:
# 3 .读取文件
# buf = f.read()
# print(buf,type(buf))
result = json.load(f) #转化为dict
print(type(result))
#姓名
print(result.get("name"))
#年龄
print(result.get("age"))
#城市
print(result.get("address").get("city"))
import json
with open('info2.json','r',encoding='utf-8') as f:
info_list = json.load(f)
print(type(info_list))
for info in info_list:
print(info.get('name'), info.get('age'), info.get('address').get('city'))
文件对象.write(字符串) 不能直接将Python 的列表 和字典 作为参数传递 想要将 Python 中数据类型存为 json 文件,需要使用json 提供的方法, 不再使用write 步骤: 1.导包 improt json 2.写(w) 方式打开文件 3.写入 json.dump(Python 中的数据类型,文件对象)
import json
my_list = [('admin','123456','登录成功')]
with open('info4.json','w',encoding='utf-8') as f:
json.dump(my_list,f,ensure_ascii=False) #直接显示中文,不以ASCII的方式显示
#显示缩进
json.dump(my_list,f,ensure_ascii=False,indent=4)
异常
程序在运行时,如果python 解释器 遇到一个错误,会停止程序执行,并且提示一些错误信息,这就是异常 程序停止执行并提示错误信息,这个动作,抛出异常(raise 关键字) 捕获异常:程序遇到异常,默认动作是终止代码程序的执行,遇见异常之后,可以使用 异常捕获,让程序代码继续运行,不会终止运行(重点!!!)
try:
书写可能发生的异常代码
except:#任何类型的异常都能捕获
发生了异常执行的代码
try:
书写可能发生异常的代码
except 异常类型:# 只能捕获指定类型的异常,如果不是这个异常,还是会报错
发生了异常执行的代码
try:
num = input("请输入数字:")
num = int(num)
print(num)
except:
print('请输入正确的代码')f'c
好处:可以针对不同的异常错误,进行单独的代码处理
try:
书写可能发生异常的代码
except 异常类型1:
发生了异常1执行的代码
except 异常类型2:
发生了异常执行的代码
except 异常类型...
发生了异常...执行的代码
完整版本中的内容,不是说每一次都要全部书写,根据自己的需要,去选择其中进行使用
try:
可能发生异常的代码
except 异常类型1:
发生异常类型1执行的代码
#Exception 是常见异常类的父类,这里书写Exception,可以捕获常见的所有异常,as 变量 ,这变量是一个异常类的对象,print(变量),可以打印异常信息
except Exception as 变量:
发生其他类型的异常,执行的代码
else:
没有发生异常会执行的代码
finally:
不管有没有发生异常,都会执行的代码
异常传递是Python中实现好了,我们不需要操作,我们知道异常会进行传递, 异常传递:在函数嵌套调用中,被调用的函数,发生了异常,如果没有捕获,会将这个异常向外层传递,...如果传到最外层,还没有捕获,才会报错
模块和包
1.python 源代码文件就是一个模块 2.模块中定义的变量 函数 类,都可以让别人使用,同样,可以使用别人定义的 (好处:别人定义好的不需要我们再次书写,直接使用即可) 3.想要使用 别人的模块中的内容工具(变量,类,函数),必须先导入模块 才可以 4.我们自己写的代码,想要作为模块使用,代码的名字需要满足标识夫的规则(数字,字母下划线组成,不能以数字开头)
在导入模块的时候,会先在当前目录中找到模块,如果找到,就直接使用 如果没有找到,则回到系统的目录中进行查找,找到,直接使用 没有找到,报错 注意点: 定义代码文件的时候,你的代码名字不能和你要导入的模块名字相同,
__name__的作用
1.每个代码文件都是一个模块 2.在导入模块的时候,会执行模块中的代码(三种方法都会) 3.__name__ 变量 3.__name__变量 是python解释器自动维护的变量 3.2 __name__ 变量,如果代码是直接运行,值是__main__
在 Python中,包 是一个目录,只不过在这个目录存在一个文件 __init__.py 将功能相近或者相似的代码放在一起 在Python 中使用的时候,不需要是区分包还是模块,使用方式是一样的 random 模块(某个代码文件) json 包(目录)
UnitTest框架
- 框架
说明: 1.框架英文单词framework 2.为解决一类事情的功能集合 需要按照框架的规定(套路) 去书写代码
- 什么是UnitTest框架
概念:UnitTest是Python自带的一个单元测试框架,用它来做单元测试 自带的框架:不需要另外按照安装,只要安装Python,就可以使用 第三方:想要使用 需要另外安装使用(pytest) 单元测试框架:主要用来做单元测试,一般单元测试是开发做的 对于测试来说,UnitTest 框架的作用是 自动化脚本(用例代码)执行框架 (使用 unittest 框架 来管理 运行 多个测试用例的)
- 为什么使用UnitTest框架
1.能够组织多个用例去执行 2.提供丰富的断言方法(让程序代码代替人工自动的判断预期结果和实际结果是否相符) 3.能够生成测试报告
- UnitTest核心要素(unitest 的组成)
TestCase(测试用例),注意这个测试用例是 unittest 框架的组成部分 不是手工和自动化中我们所说的用例(Test case) 主要作用:每个 TestCase(测试用例) 都是一个代码文件,在这个代码文件中 来书写真正的用例代码 TestSuit(测试套件),用来管理 组装多个 TestCase(测试用例) TestRunner(测试执行,测试运行) 用来去执行 TestSuite(测试套件)的 TestLoader(测试加载),功能是对 TestSuite(测试套件) 功能的补充, 管理 组装(打包)多个 TestCase(测试用例)的 Fixture(测试夹具),书写在 TestCase() 代码中, 是一种代码结构,可以在每个方法执行前后都会执行的内容 举例: 登录的测试用例,每个用例中重复的代码就写可以写在 Fixture 代码结构中,只写一遍,但每次用例方法的执行,都执行Fixture中代码 1.打开浏览器 2.输入网址
-
TestCase(测试用例)
""" 案例练习 """ #1.导包 import unittest #2.自定义测试类 import tool class TestAdd(unittest.TestCase): #测试方法 def test_method1(self): if tool.add(1,2) == 1+2: print('测试通过') else: print('测试失败') def test_method2(self): if tool.add(1,3) == 1+3: print('测试通过') else: print('测试失败') def test_method3(self): if tool.add(1,5) == 1+5: print('测试通过') else: print('测试失败') -
TestSuite 和 TestRunner
import unittest #实例化套件对象 from testcase import TestAdd suite = unittest.TestSuite() #添加测试方法 suite.addTest(unittest.makeSuite(TestAdd)) #实例化执行对象 runner = unittest.TextTestRunner() runner.run(suite)
-
TestLoader(测试加载)
TestLoader(测试加载),作用和TestSuite 的作用是一样的,对 TestSuite 功能进行补充,用来组装测试用例 比如:如果TestCase 代码文件有很多,(10 20 30)
使用步骤 1.导包 2.实例化测试加载对象并添加用例 ——————>得到的是 suite对象 3.实例化 运行对象 4.运行对象执行套件对象
-
代码实现
在一个项目当中 TestCase(测试用例) 的代码一般放在一个单独的目录当中(case)
"""TestLoader 的使用""" #1.导包 import unittest #2.实例化加载对象并添加用例 #unittest.TestLoader().discover('用例的所在路径','用例的代码文件名') #用例所在路径,建议使用相对路径,用例的代码文件名可以使用 *(任意多个任意字符) 通配符 suite = unittest.TestLoader().discover('./case','test*.py') #3.实例化运行对象 runner = unittest.TextTestRunner() runner.run(suite)#1.导包 #2.使用默认的加载对象并加载用例 #3.实例化运行对象并运行
Fixture(测试夹具) 是一种代码结构 在某些特定的情况下,会自动执行
在每个测试方法(用例代码) 执行前后都会自动调用的结构
# 方法执行之前
def setUp(self):
#每个测试方法执行之前都会执行
pass
# 方法执行之后
def teardown(self):
#每个测试方法执行之后都会执行
pass
在每个测试类中所有方法执行前后,都会自动调用的结构(在整个类中 执行之前执行之后一次)
# 类级别的Fixture 方法,是一个 类方法 # 类中所有方法之前 @classmethod def setUpClass(cls): pass #类中所有方法之后 @classmethod def teardownClass(cls): pass
模块:代码文件 在每个代码文件执行前后执行的代码结构
#模块级别的需要写在类的外边直接定义函数即可
# 代码文件之前
def setUpModule():
pass
#代码文件之后
def teardownModule():
pass
方法级别和类级别 前后的方法,不需要同时出现,根据用例代码的需要自行的选择使用
1.打开浏览器(整个测试过程中就打开一次浏览器) 类级别 2.输入网址 (每个测试方法都像需要一次) 方法级别 3.输入用户名 密码 验证码 点击登录(不同的测试数据) 测试方法 4.关闭当前页面 (每个测试方法都需要一次) 方法级别 5.关闭浏览器 类级别 -------
import unittest
class TestLogin(unittest.TestCase):
def setUp(self) -> None:
"""每个测试方法执行之前都会调用的方法"""
print('输入网址....')
def tearDown(self) -> None:
"""每个测试方法执行之后都会调用的方法"""
print('关闭当前页面....')
@classmethod
def setUpClass(cls) -> None:
print('1.打开浏览器')
@classmethod
def tearDownClass(cls) -> None:
print('2.关闭浏览器')
def test_1(self):
print('输入用户名密码验证码,点击登录 1 ')
def test_2(self):
print('输入错误用户名密码验证码,点击登录 2')
断言
让程旭代替人工自动的判断预期结果和实际结果是否相符 断言的结果有两种 Ture 用例通过 False 代码抛出异常,用例不通过
assertEqual(预期结果,实际结果) #判断预期结果和实际结果是否相等 1.如果相等,用例通过 2.如果不相等,用例不通过,抛出异常
assertIn(预期结果,实例结果) #判断预期结果是否包含在实际结果中
1.包含,用例通过
2.不包含,用例不通过,抛出异常
assertIn('admin','admin') #包含
assertIn('admin','adminnnnn') #包含
assertIn('admin','aaaadminnn') #包含
asserttIn('admin','addddmin') #不是包含
参数化,在测试方法中,使用 变量 来代替具体的测试数据,然后使用传参的方法将测试数据传递给方法的变量 好处:相似的代码不需要多次书写 工作中场景: 1.测试数据一般放在 json 文件中 2.使用代码读取json 文件,提取我们想要的数据 ---->[()()()] or [[],[],[]]
unittest 框架本身是不支持参数化,想要使用参数化,需要安装插件来完成 - 联网安装(在cmd 窗口安装) - pip install parameterized ------- pip 是 python 中包(插件) 的管理工具,使用这个工具下载安装插件
验证
pip list #查看到 parameterized 新建一个 python 代码文件,导包验证 from pa... import pa....
参数化代码
1.导包 unittest/pa 2.定义测试类 3.书写测试方法(用到的测试数据使用变量代替) 4.组织测试数据并传参
# 1.导包 unittest/pa
import unittest
from parameterized import parameterized
# 2.定义测试类
from login import login
#组织数据
data = [
('admin','123456','sucessful'),
('root','123456','defect'),
('admin','123123','defect'),
]
class TestLogin(unittest.TestCase):
# 3.书写测试方法(用到的测试数据使用变量代替)
@parameterized.expand(data)
def test_login(self,username,password,expect):
self.assertEqual(expect,login(username,password))
# 4.组织测试数据并传参(装饰器)
正在上传…重新上传取消
# 1.导包 unittest/pa
import json
import unittest
from parameterized import parameterized
# 2.定义测试类
from login import login
#组织数据这边用的是将json中的数据传过来
def build_data():
with open('test.json',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.组织测试数据并传参(装饰器)
对于一些未完成的或者不满足测试条件的测试函数和测试类,不想执行,可以使用跳过使用方法,装饰器完成 代码书写在 TestCase 文件
# 直接将测试函数标记成跳过
@unittest.skip('跳过的原因')
# 根据条件判断测试函数是否跳过,判断条件成立,跳过
@unittest.skipIf(判断条件,'跳过原因')
import unittest
version = 29
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')
只有单独运行 TestCase 的代码,才会生成测试报告
1.获取第三方的 测试运行类模块,将其放在代码的目录当中 2.导包 unittest 3.使用 套件对象,加载对象,去添加用例方法 4.实例化 第三方运行对象,并运行 套件对象
import unittest
from HTMLTestRunner import HTMLTestRunner
# 3. 使用 套件对象,加载对象 去添加用例方法
suite = unittest.defaultTestLoader.discover('.','pa1.py')
#4. 实例化 第三方的运行对象 并运行 套件对象
HTMLTestRunner()
#stream = sys.stdout 必填,测试报告的文件对象(open),注意点,要使用wb 打开
#verbosity = 1, 可选,报告的详细程度,默认 1 简略,2 详细
#title = None ,可选,测试报告的标题
#description = None 可选,描述信息,Python的版本,pycharm版本
file = 'report.html'
with open(file,'wb') as f:
runner = HTMLTestRunner(f,2,'测试报告') #运行对象
# #运行对象执行套件
runner.run(suite)
流程
1.组织用例文件(TestCase 里边),书写参数化,书写断言,书写Fixture,书写,跳过,如果只有单个测试文件,直接运行,得到测试报告,如果有多个测试文件,需要组装运行生成测试报告 2.使用 套件对象进行组装,或者使用 加载对象组装 3.运行对象, 运行 3.1 运行对象 = 第三方的运行类(文件对象(打开文件需要使用 wb 打开方式)) 3.2 运行对象.run(套件对象)
本文介绍了Python的基础语法,包括变量、数据类型、字符串操作、列表和元组的使用,以及字典和集合的概念。进一步讲解了面向对象编程,包括类的创建、对象的实例化、继承、多态和封装。还探讨了Python中的异常处理、文件操作和JSON操作。此外,简述了unittest测试框架的使用,包括测试用例、参数化测试、测试报告和断言。
3673

被折叠的 条评论
为什么被折叠?



