简介
python只是一个变成语言,工作中需要结合其他工具使用
python + selenium web 自动化(功能测试转换为代码)
python + appium 移动端(手机APP)自动化
python + requests 接口
print函数
print()是python自带的函数,作用在控制台中输出,括号中的内容后续看到这个函数就是输出打印数据的,或者想要在控制台中显示某个内容,就要使用print()函数
print()函数中是什么内容,就会显示什么,可以是“”也可以是‘’
注释
python中的注释有俩种,单行注释和多行注释
单行注释
使用井号和空格进行注释(单独y一个#也可以)
快捷方式 ctrl /
多行注释
多行注注释中的内容 可以换行书写
多行注可以使用3对双引号或者3对单引号,被三对引号包括的内容就是注释的内容
三对引号的注释一般写到一开始处,或者文档注释处(函数)
代码中的波浪线和PEP8
红色:红色是代码的错误,必须把错误解决才能执行
灰色:不会影响代码的正常执行
PEP8:python代码的书写规范,如果不按照书写规范就会出现灰色波浪线 ,建议代码书写按照PEP8的规范书写
1.书写代码时注意用PEP8的规范
2.可以在书写完成后,使用快捷键Ctrl Alt L 来按照PEP8的规范自动格式化代码
绿色:不影响代码的正常运行,认为你书写的内容不是一个单词
变量
作用:是用来存贮数据的(在程序代码中出现的数据,想要保存下来使用,就必须使用变量)如:测试数据,用户名,密码,验证码
变量注意使用:变量必须先定义(保存数据)后使用(取出数据)
定义变量
变量名=数据值 # 将数据值保存到变量中
使用变量
变量定义后,想要使用变量中的数据,直接使用变量名即可
name='张三' print(name)# 张三
使用变量打印是不需要引号
name='张三' print('name') #name
添加引号后就会输出引号中的内容
变量名的命名规则
起名的规范,标识符的规则
1.必须由字母数字下划线组成,并且不能以数字开头
2.不能用书python中的关键字
3.区分大小写
4.建议性命名
!驼峰命名法
1.大驼峰:每个单词的首字母大写 MyName 小驼峰:第一个单词的首字母 小写,其余单词的首字母大写myNAME
下划线连接my_name
python 中的变量定义使用的是下划线连接
见名知意
数据类型
整形(int),就是整数,即不带小数点的数
浮点型(float),就是小数
布尔类型(bool),只有两个值
1.真(True) 1 2.假(False)0,非0即真
True跟False都是python中的关键字,注意大小写不要写错了
复数类型3+4i,不会用的
非数字类型
字符串:(str)使用引号引起来的就是字符串
列表(list)[1,2,1]
原组(tuple)(1,2,4,4)
字典(dict){‘name’:‘小明,‘age’:15}
type()函数
可以获取变量的数据类型
type(变量)
想要将这个变量的类型在控制台显示,需要使用print输出
print(type(变量))
输入
获取用户使用键盘录入的内容
使用的函数是input()
变量=input(‘提示的信息’)
数据类型转换
输出
输出使用的是print()函数,作用,将程序中的数据或结果打印到控制台(屏幕)
print(‘hello world’)
name=‘小明’
print(name)
age=18
print(name,age)#使用逗号输出多个内容
格式化输出
在字符串中指定的位置,输出变量中存储的值,
1.在需要使用变量的地方,使用特殊符号站位
2.使用变量填充占位的数据
%格式化输出占位符号
%d 占位,填充 整型数据digit
%f 占位,填充 浮点型数据float
%s 占位, 填充 字符串数据 string
age = 18 height = 18 name = '小明' 及格率 = 90 print('他的名字为: %s,身高 %.1f,年龄%d' % (name, height, age)) print('他的及格率为: %d%%' %及格率 )
# 当需要输出一个%时,需要两个%
F-string(f字符串的格式化方法)
1.需要在字符串前面加f或F
2.占位符统一为{}
3.需要填充的变量,写在{}中
运算符
算数运算符
字符串的格式化补充
字符串.format()、
1.在需要使用 变量的地方使用{}占位
2.‘{},{}....’.format(变量,变量......)
逻辑运算符
and 一假则假 or 一真则真 not 取反
赋值运算符
=,将等号右边的值保存到左边的变量中
运算符优先级,不需要刻意去记,()刻意改变优先级
判断
if else elif
在代码中有判断语句,代码不会全部执行,有一部分不会执行
if的基本结构
如果的条件成立,会执行的代码,会做的事
基本语法
if 判断条件:
书写条件成立(真),执行的代码
定格书写,没有缩进的代码,与if无关,不管条件是否成立,都会执行
#1.if是一个关键字 ,和后续的判断条件之间需要一个空格
#2.判断条件后面需要一个:
#3.冒号之后,回车,代码需要缩进,在pthcharm中自动进行缩进,一般是4个空格或者一个tab健
#4.所有在if代码块下方的缩进中书写的代码,属于if语句的代码块,判断为true时执行
#5.if中的代码块,要么都执行,要么都不执行
#6.if代码块结束之后,代码要定格书写(不再有缩进),表示是和if无关的代码
if else
基本语法
if 判断条件:
书写条件成立(真),执行的代码
else:
书写条件不成立(假),执行的代码
# 1.else 是关键字,后面需要冒号
2.冒号回车后同样需要缩进
3.处于else 代码下方缩进中的内容,属于else 的代码块
4.if 和 else 的代码块,只会执行其中的一个
5.else 需要配合if 使用
DEBUG
debug 在代码出现问题错误(bug),可以使用debug来调试代码,查找错误,我们使用debug主要用来查看代码执行步骤
1.打断点
在pychar中,代码和行号之间进行点击,出现小红点及打断点
断点的位置,一般来说在代码的第一行(在程序运行的时候,想要在什么地方停下来)
随机出拳
案例中需要电脑随机出拳,及随机出1,2,3
在python中想要随机获得整数数字可以使用如下方法
1.导入随机数工具包
import random
2.使用工具包中的工具产生指定范围的数字
random.randint(a,b) #产生【a,b】之间的随机数,包含a,b
import random #这行代码一般来说放在第一行
循环
语法
1.设置循环的初始条件(计数器)
2.书写循环的判断条件
while 判断条件:
#需要重复的代码
#改变循环的初始条件
死循环
while True:
重复执行的代码
if 判断条件:
break #是python的关键字,直接跳出循环
for循环
for循环可以让指定的代码重复执行(循环)
for循环可以遍历容器中的数据(
遍历:从容器中把数据一个一个取出
容器:可以简单理解为盒子,盒子中可以存放很多的数据(字符串str,列表list,元组tuple,字典dict)
)
for循环可以称为for遍历
语法:
for 变量名 in 容器:
重复执行的代码
for做指定次数的循环
for 变量 in range(n):
重复执行的代码
1.in range()是python中的函数,作用可以生成[0,n)之间的整数,不包含n的,一个有n个数字,所以循环几次
2.想让for循环几次,n就写几
3.第一次取的值是0,最后一次是n-1
rang()变形
for 变量 in range(a,b):
重复的代码
# 作用是生成[a,b)之间的整数
break 和 continue
break和continue是python中的两个关键字,只能在循环中使用
break:终止循环,即代码执行遇到break,循环不在执行,立即结束
continue:跳过本次循环,即遇到代码
容器
容器:数据序列,也是高级数据类型,也是python中的数据类型
容器中可以放多个数据。
字符串
字符串是容器,因为字符串中包含多个字符
使用引号(单引号,双引号,引号)引起来的内容就是字符串
下标
下标(索引):就是指字符在字符串中的位置编号,这个编号就是下标
这个编号一般来说都是从左到右进行编号的,从0开始(python中支持负数下标,从右到左进行编号,从-1开始)
语法:
字符串[下标] #获取指定位置的字符
获取字符串的长度 len(字符)
切片
切片:可以获取字符串中多个字符(多个字符的下标都是有规律的,等差数列)
语法:
字符串[strar:end:step]
1.strar:是开始位置的下标,end是结束位置的下标(注意:不能取到这个位置的字符,step步长,等差数列的差值,所相邻字符下标之间的插值,默认是1,可以不写)
字符串的查找
用法:
字符串.find(sub_str,strar,end)
作用:在字符串中查找是否存在sub_str 这样的字符串
sub_str:要查找小的字符串
strar:开始位置,从哪个下标位置开始查找。一般不写,默认为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:字符串按照什么进行拆分,默认是空白字符(空格,换行,tab)
max_split,分割次数,一般不写,全部分割
返回:将一个字符串拆分为多个,存到列表中
注意:如果sep不写,想要指定分割次数则按照如下方式使用
字符串.split(max_split=n) #n是次数
字符串的链接join
字符串.join(列表)#括号中的内容主要是列表,可以是其他容器
#作用:将字符串插入到列表中每相邻的两个数据之间,组成一个新的字符串
- 列表中的数据使用 用逗号分开
- 注意点:列表中的数据必须是字符串,否则回报错
列表
列表list ,是使用最多的一种容器(数据类型)
列表中可以存放多种数据类型,每个数据类型使用逗号隔开
列表中可以存放任意类型的数据
列表支持下标和切片操作
查找列表中数据下标的方法
在字符串中使用find方法查找下标的,不存在返回的是-1
在列表中没有find方法,想要查找数据的下标,使用index()的方法
列表.index(数据,start,end)使用find方法一样,在字符串中也有inde()方法
区别:返回,index()方法,找到返回第一次出现的下标,没有找到代码直接报错
查找-判断是否存在
判断容器中某个数据是否存在可以使用in关键字
数据 in 容器 #如果存在返回Ture ,如果不存在返回False
查找-统计出现的次数
统计出现的次数,使用的是count()方法
列表.count(数据) #返回 数据出现的次数
添加数据的方法
--尾部添加(最常用)
列表.append(数据) #将数据添加到列表的尾部
返回:返回None(关键字,空),一般就不再使用变量来保存返回的内容
想要查看添加后的列表,需要打印的是列表
--指定下标位置添加
列表.insert(下标,数据) #在指定的下标添加数据,如果指定的位置有数据则源数据会后移
返回:返回None(关键字,空),一般就不再使用变量来保存返回的内容
想要查看添加后的列表,需要打印的是列表
--列表合并
列表1.extend(列表2) #将列表2中的所有数据逐个添加到列表的尾部
列表修改
lis1[下标] =要修改的内容
列表删除
在列表中删除中间的数据,则后面的数据像前面移动
--根据下标删除
列表.pop(下标)#删除指定下标位置对应的数据
1.下标不写,默认删除最后一个数据
2.书写存在的下标,删除对应下标位置的数据
返回:返回删除的数据
--根据数据值删除
列表.remove(数据值)# 根据数据值删除
返回None
如果数据不存在则会报错
清空数据
列表.clear
列表的反转
字符串中 反转倒置:字符串[::-1]
列表中 反转和倒置:
1.列表[::-1]使用切片的方法将列表倒置,源列表不发生改变
2.列表.reverse() #直接修改原列表,返回None
列表的复制
将列表中的数据复制一份,给到新的列表
1.使用切片
变量=列表[:]
2.使用copy方法
变量=列表.copy()
列表的排序
列表的排序,一般来说都是对数字进行排序的
列表.sort()#按照升序排序,从小到大
返回值none直接修改原列表
列表.sort(reverse=Ture) #降序排序,从大到小
返回值none 直接修改原列表
列表嵌套
列表中的内容还是列表
使用下标来确定获取的是什么类型的数据,然后确定可以继续进行的操作
元组
元组:tuple,元组的特点和列表非常相似
1.元组可以存放任意类型的数据
2.元组可以存放任意多个数据
区别:
1.元组中的数据内容不能改变,列表中可以改变
2.元组是用(),列表使用[ ]
应用:在函数传参和返回值时使用,保证数据不会改变
定义
1.使用 类实例化方式
2.直接使用()方式
常用方法
由于元组中数据不能改变,只能进行查看
1.在元组中可以使用下标和切片获取数据
2.在元组中存在index 方法,查找下标,如果不存在。则会报错
3.在元组中存在count 方法,统计数据出现的次数
4.在元组中可以使 用 in 操作,判断数据是否存在
5.len()统计个数
以上方法和列表中的使用是一样的
列表转换成元组与字符串转换成元组例:
注:元组中有一个数据时一定要加逗号 tuple=(1,)
字典
1.字典dict,字典中的数据有键(key)值(value)对组成(键表示数据的名字,值就是具体的数据)
2.在字典中一组键值对对一个数据,多个键值对之间使用,逗号隔开变量={kye:value,key:value...}
3.一个字典中的键是唯一的,不能是重复的,值可以是任意数
增加和修改操作
语法
字典[键]=值
如果数据已经存在,则就是修改
如果没有数据存在,就是增加
字典操作实例:
删除
删除指定键值对
del 字典[键]
清空
字典.clear()
查询-根据键获取对应的值
字典中没有下标的概念,想要获取数据值,要使用key(键)来获取
-使用字典[键]
字典[键]
1.如果键存在。则返回键对应的数据值
2.如果键不存在,会报错
-使用字典.get(键)
字典.get(键,数据值)
1.数据值一般不写,默认为none
返回:
1.如果键存在。则返回键对应的数据值
2.如果键不存在,返回括号中书写的数据值(None)
一般建议使用get方法
mydict = {'name': 'liming', 'sex': '男', 'like': ['抽烟', '喝酒', '烫头']} print(mydict.get('name')) #liming print(mydict['like']) #['抽烟', '喝酒', '烫头'] print(mydict['like'][2]) #获取like中的 第三个数据
字典的遍历
for 变量 in 字典:
print(变量) #变量就是字典的kye 键
for 变量 in 字典.keys(): #字典.kyes()可以获取字典中所有的键、
print(变量)
对字典的值进行遍历
for 变量 in 字典.values(): #字典.values ()可以获取字典中所有的值
print(变量)
对字典的键值对进行遍历
mydict = {'name': 'liming', 'sex': '男', 'like': ['抽烟', '喝酒', '烫头']} for i in mydict: print(i) # sex like name for n in mydict.keys(): print(n) # sex like liming for v in mydict.values(): print(v) # liming 男 ['抽烟', '喝酒', '烫头'] for x, z in mydict.items(): #name liming print(x, z) #sex 男 #like ['抽烟', '喝酒', '烫头']
容器的部分总结
1.元组,列表,字符串支持加法运算
2.元组,列表,字符串支持乘一个数字
str = 'like' str2 = 'me' str3 = str + str2 print(str3) #likeme list1=[1,6,6]+[5,9,4,6] print(list1) #[1, 6, 6, 5, 9, 4, 6] tuple1=('as',1)+(2,6) print(tuple1) #('as', 1, 2, 6) str5='like'*3 print(str5) #likelikelike list6=[1,3]*6 print(list6) #[1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3] tuple7=('aas',6,56,798)*2 print(tuple7) #('aas', 6, 56, 798, 'aas', 6, 56, 798)
函数
函数,就是把具有独立功能模块的代码块,组织为一个小模块,在需要的时候调用
函数,通俗理解,将多行代码写在一块,起个名字,在需要这多行代码的时候,可以直接使用这个名字来代替
函数好处:减少代码的冗余,提高程序的编写效率
函数定义
1.将多行代码放在一起,起名字的过程
2.函数必须先定义后调用
语法
def 函数名():
函数中的代码
函数中的代码
#1.def是关键字,用来定义函数 define的缩写
#2.函数名需要遵守标识符的规则
#3.处于def 缩进中的代码成为函数体
4.函数定义的时候,函数体重的代码不会执行,在调用的时候才会去执行
函数定义技巧:在前期,书写不熟练的时候,1.可以先不管 函数,先把功能写出来2.给多行代码起名字3.选中多行代码,使用tab缩进
函数的调用
1.使用函数的过程,称为函数的调用
语法
-函数名()
1.函数调用的时候会执行函数体中的代码
2.函数调用的时候,要写在函数体外面
文档注释
文档注释,也是注释,作用:主要告诉其他程序员这个函数是干什么的
在函数名下方使用三个双引号
查看:在调用的时候,将光标放到函数名上,使用快捷键ctral+q(Windows)、
def sayhello(): """三个hello""" print('hello 1') print('hello 2') print('hello 3') sayhello()
列表去重
列表去重:列表中存在多个数据,需求,去除列表中重复的数据
方式1. 思路
遍历原列表中的数据判断在新列表中是否存在,如果不存在,不管,如果不存在放入新列表中
遍历:for 循环实现
判断是否存在:可以使用in
存入数据append()
方法2.:
在python中还有一种数据类型(容器),称为集合(set)
特点:集合中不能有重复的数据(如果有重复的数据会自动去重)
1.使用set()类型转换将列表转换为集合类型
2.使用list()类型转换为列表类型
缺点:不能保证数据在源列表出现的数据(一般来说,也一般不考虑)
list1=[1,1,2,3,4,6,1,3,2,1,] new = [] for i in list1: if i not in new : new.append(i) print(new)\
函数基础
函数的参数
含义:在函数定义的时候,使用变量代替具体的数据值,在函数调用的时候,传递具体的数据值
好处:让函数更加通用,能够解决一类问题,而不是单纯的一个
函数的返回值,可以理解为是函数整体执行的结果是什么
print ---》None
input()--》键盘输入的内容
type()---》类型
len()--》数据的长度(元素的个数)
在函数中想要将一个数据作为返回值返回,需要使用return关键字(只能在函数中使用)
作用:
1.将数据值作为返回值返回
2.函数代码遇到retrun,会结束函数的执行
返回值说明
def 函数名(): #返回值None
pass #代码中没有return
def 函数名():
return #rreturn后面没有返回值,返回None
def 函数名():
return XX #return返回xx
变量进阶
在这部分 我们了解python 底层是如何处理数据的
变量的引用
1.在定义变量的时候 变量=数据值, python 解释器会在内存中开辟两块空间
2.变量和数据都有自己的空间
3.日常简单理解,将数据保存到变量的内存中,本质是将数据地址保存到变量对应的内存中
4.变量中存贮数据地址的行为 就是引用(变量引用了数据的地址,简单来说就是变量中存贮数据),存贮地址称为引用地址
5.可以使用id()函数可以查看变量中保存数据所在的内存地址,如果两个变量的id()获取的引用地址一样,即代表,变量引用了同一个数据,是统一一个数据
6.python中数据的传递,都是传递的引用
可变类型和不可变类型
数据类型: int float bool str list tuple dict set
可变和不可变指:数据所在的内存是否允许修改,允许修改就是可变类型,不允许修改就是不可变类型
可变类型:列表list ,字典 dict ,集合set
不可变类型:int float bool str tupe
两个数据交换
python 特有方法
a=10 b=20 a,b=b,a print(a,b)
组包和拆包
组包(pack):多个数据使用逗号连接,组成元组
拆包(unpack):将容器中的 数据值使用多个变量分别保存的过程,注意:变量的个数和容器中数据的个数要保持一致
赋值运算,都是先执行等号右边的代码,执行结果,保存到等号左边的变量中
a=10 b=20 c=a,b #组包 print(type(c), c) #<class 'tuple'> (10, 20) a,b=c #拆包 print(a, b) #10 20
局部 变量和全局变量
变量:根据变量定义位置,可以将变量分为局部变量和全局变量
局部变量
局部变量:在函数内部定义的变量,称为局部变量
特点:
1.局部变量只能在当前函数内部使用,不能再 其他函数和函数外部使用
2.在不同函数中,可以定义名字相同的局部变量,两者之间没有关系
全局变量
定义位置:在函数外部定义的变量,称为全局变量
特点:
1.可以在任何函数中读取全局变量的值
2.如何在函数中存在全局变量名字相同的局部变量,在函数中使用的局部变量的值
3.在函数内部想要修改全局变量的引用,需要添加global关键字 ,对变量进行声明为全局变量
4.声明周期
代码执行的时候被创建,代码执行结束, 被销毁
返回值-函数返回多个数据值
函数中想要返回一个数据值,使用return关键字
将多个数据值组成容器进行返回,一般元组(组包)
函数参数
位置传参:
在函数调用的时候,按照形参的顺序,将实参值传递给形参
关键字传参
在函数调用的时候,指定数据值给到那个形参
混合使用
1.关键字传参必须写在位置传参的后面
2.不要给个一个形参传递多个数据值
缺省参数
缺省参数,默认参数
列表.pop()# 不写参数,删除最后一个
列表.sort(reverse)
1.定义方式
在函数定义的时候,给形参一个默认的数据值,这个形参就变为缺省参数,注意,缺省参数的 书写要在普通参数后面
2.好处
缺省参数,在函数调用的时候,可以传递实参值,也可以不传递实参值
如果传参 ,使用的就是传递的实参值,如果不传参,使用的就是默认值
def inforp(name,sex='man'): print(name,sex) inforp('李明') #李明 man inforp('小明','女') #小明 女
多址参数[可变参数/不定长参数]
print(1)
print(1,2)
print(1,2,3)
print(1,2,3,4)
当我们书写函数的时候,不确定参数的具体个数,可以使用不定长参数
-不定位置参数(不定长元组参数)
1.书写,在普通参数的前边,加上一个*,这个参数就变为不定长位置参数
2.特点,这个形参有接受任意多个位置传参的数据
3.数据类型,形参的类型是元组
4.注意,不定长位置参数 要写在普通参数的后面
5.一般写法,不定长参数的名字为args,即(*args)
-不定长关键字参数(不定长字典参数)
1.书写,在普通参数的前片,加上两个*,这个参数就变为不定长关键字参数
2.特点,这个参数可以接收任意多个关键字传参的数据
3.数据类型,形参的类型是字典
4.注意,不定长关键字参数,要写在所有参数的最后面
5.一般写法,不定长关键字的名字 为kwargs,即(**kwargs)
完整顺序
def 函数名 (普通函数,*args,缺省参数,**kwargs)
pass
def num_3(*args, **kwargs): num = 0 for i in args: num += i for j in kwargs.values(): num += j print(num) num_3(1, 6, a=10) list9=[1,6,3,6,4] dict_7={'a':1,'b':6,'c':3,'d':6,'e':4} num_3(*list9) #20 num_3(**dict_7) #20
当形参需要放入列表或者元组或字典时,需要拆包,*列表/元组,**字典
-函数部分
--不定长参数的补充扩展
--匿名函数 lambda
-面向对象
匿名函数:就是用lambda关键字定义的函数
一般称为使用def 关键字定义的函数为 ,标准函数
匿名函数只能书写一行代码
匿名函数的返回值不需要returen,一行代码的结果就是返回值
语法:
lambda 参数:一行代码
#匿名函数一般不需要我们主动的调用,一般作为函数的参数使用
#我们在学习阶段为了查看匿名函数定义的是否正确,可以调用
func8 = lambda a,b:a*b print(func8(1,6))
使用场景:作为函数的参数
匿名函数作为函数的参数-列表中的字典排序
列表排序
列表.sort()升序
列表.sort(reverse=Ture)降序
#列表的排序,默认是对列表中的数据进行比大小,可以对数字类型和字符串进行比大小
#但是对于字典来说,就不知道该怎样比大小,此时,我们需要使用sort函数中的key这个参数,来指定字典比大小的方法
列表.sort(kye=lambda x:x[‘键’])
说明:匿名函数中的参数是列表中的数据,在sort 函数内部,会调用key这个函数(将列表中每个数据作为实参传递给形参)
从列表中的函数的返回值,对返回值进行比大小的操作<>
字符串比大小
字符比大小,是比较字符对应的asscii码
ord(字符)获取字符对应的asscii码
chr(asscii码)获取对应asscii码
面向对象
基本介绍
面向对象是一个编程思想(代码套路)
编程思想:
1.面向过程:
关注的是具体步骤的实现,所有的功能都自己书写
亲力亲为
定义一个个函数,最终按照顺序调用函数
2.面向对象
以上两种都属于写代码的套路(方法)最终目的都是为了将代码写出来,只不过 过程和思考方法不太一样
关注的是结果,谁能帮我做这件事
偷懒
找一个对象(),让对象去做
类的组成
1.组成(给多个事物起一个名字,代码中,满足大驼峰命名法(每个单词的首字母大写))
2.属性(事物的特征,即有什么,一般文字中的名词)
3.方法(事物的行为,即做什么,一般是动词)
类的抽象(类的设计)
类的抽象,其实就是找到类的类名,属性和方法
面向对象基本代码的书写
1.定义类
先定义简单的类,不包含属性,在python中定义类需要使用关键字class
方法:方法的本质是在类中定义的函数,只不过,第一个参数是self
class 类名:
#在缩进中书写的内容,都是类中的代码
def 方法名(self):
pass
2.创建对象
创建对象是使用 类名()进行创建,即
类名() 创建一个对象,这个对象在后续不能使用
变量=类名()#这个变量中保存的是对象的地址,一般可以称为这个变量为对象
3.调用方法
对象.方法名()
列表.sort()
列表.append()
实例
class Cat: def eat(self): print('小猫还吃鱼') def drink(self): print('小猫爱喝水') blue_cat=Cat() blue_cat.eat() #小猫还吃鱼 blue_cat.drink() #小猫爱喝水
self 的说明
从函数的语法上讲,self是形参,就可以是任意的变量名,只不过我们习惯性的将这个形参写作self,
2.self是普通的形参,但在调用的时候没有传递实参值,原因是在python解释器在执行代码的时候,自动的调用这个方法的对象,传递给self,即self的本质是对象
对象的属性操作
添加属性
对象.属性名=属性值
--类内部添加
在内部方法中,self是对象
self.属性名=属性值
#在类中添加属性一般写作__init__方法中
-类外部添加
对象.属性名=属性值 #一般不用
魔法方法
python中有一类 方法,以两个下划线开头,两个下划线结尾,并且在满足某个条件的情况下,会自动调用,这类方法称为魔法方法
__init__方法
1.什么情况下会自动调用
》创建对象之后会自动调用
2.有什么用,用在哪
》1.给对象添加属性的,(初始化方法,构造方法)2.某些代码,在每次创建对象之后,都要执行,可以将这行代码写在__init__ 方法
3.书写注意
》1.不要写错2.如果有除了self以外的参数,还要穿对应的实参
class Cat: def __init__(self,name,age): self.name =name self.age = age def show_S(self): print(f'小猫的名字是:{self.name},年龄:{self.age}') blue_cat = Cat('黑猫',12) blue_cat.show_S() #小猫的名字是:黑猫,年龄:12
__str__方法
class Cat: def __init__(self, name, age): self.name = name self.age = age def __str__(self): # 方法必须返回一个字符串,只要是字符串就行 return f'小猫的名字是:{self.name},年龄:{self.age}' blue_cat = Cat('黑猫', 12) print(blue_cat) #小猫的名字是:黑猫,年龄:12
__ del__
__init__方法,创建对象后,自动调用
__del__方法,对象被销毁后,自动调用(遗言,自动处理)
家居案例
class Houseltem(): 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, total_area): self.name = name self.total_area = total_area self.free_area = total_area self.item_list = [] def __str__(self): return f'房子的户型是{self.name},总面积{self.total_area}m²,剩余面积{self.free_area}m²,家具名称为{self.item_list}' def add_item(self, item): if self.free_area > item.area: self.free_area -= item.area self.item_list.append(item.name) print(f'{item.name}添加成功') else: print(f'{item.name}添加失败') chest = Houseltem('衣柜', 2) bed = Houseltem('席梦思', 4) table = Houseltem('餐桌', 1.5) print(bed) print(chest) print(table)
结果 家具的名字为席梦思,占地面积4平米
家具的名字为衣柜,占地面积2平米
家具的名字为餐桌,占地面积1.5平米
房子的户型是三室一厅,总面积150m²,剩余面积150m²,家具名称为[]
席梦思添加成功
房子的户型是三室一厅,总面积150m²,剩余面积146m²,家具名称为['席梦思']
私有和公有
1.在python中定义的方法和属性,可以添加访问控制权限(即在什么地方可以使用这个属性个方法)
2.访问控制权限分为两种,公有权限和私有权限
3.公有权限
》直接书写的方法的属性,都是公有的
》公有方法和属性,可以在任意地方访问和使用
4.私有权限
》在类内部,属性名或者方法名 在前面加上两个 下划线,这个属性或这方法就变为私有的
》私有方法和属性,只能在类的内部使用
5.什么时候定义私有
1.某个属性或者方法,不想在类外部访问和使用,就定义为私有
2.测试中,一般不怎么使用,直接公有即可
3.开发中,会有需求文档,确定什么私有
继承
1.继承描述的类与类之间的关系
2.继承的好处:减少代码的冗余(相同的代码不需要多次重复书写),可以直接使用
语法
class A: #没有写父类,也有父类,object,object类是python中最顶级的类
pass
class B(A):
pass
1.A类,称为是父类(基类)
2.B类,称为是子类(派生类)
继承之后的特点:
子类继承父类之后,子类的对象可以直接使用父类定义的公有的属性和方法
class Animal(): def eat(self): print('吃东西') class sleep(Animal): def sleep(self): print("睡觉") class xtq(sleep): pass a = xtq() a.eat() #吃东西 a.sleep() #睡觉
结论
python中 对象.方法()调用方法
1.现在自己的类中去找有没有这个方法,如果有,直接调用
2.如果没有去父类中 查找,如果有,直接调用
3.如果没有,去父类的父类去查找,如果有,直接调用
4..
5.如果object 类中有,直接调用,如果没有,直接报错
覆盖
1.直接在子类中定义和父类相同的方法
.2.直接在方法中重新书写
扩展
1.直接在子类中定义和父类相同的方法
2.在合适的地方调用父类中方法 super().方法()
3.书写添加的新功能
多态
1.是一种写代码,调用的技巧
2.同一个方法,传入不同的对象,执行得到不同的结果,这种现象称为多态
属性和方法
python中一切皆对象
即 使用class定义的类
方法的划分
方法,使用def 关键字定义在类中的函数就是方法
实例方法
-定义
#在类中直接定义的方法就是实例方法
class Demo:
def func(self):#参数一般写作self,表示 实例对象
pass
定义时机(什么时候用)
类方法(会用)
-定义
#在方法名字的上方书写@classmethod装饰器(使用@classmethod 装饰方法)
class Demo:
@classmethod
def func(cls):#参数一般是cls,表示的是类对象class
pass.
定义时机(什么时候用)
1.前提,方法中不需要使用 实例属性(即self)
2.用到了类属性,k可以将这个方法定义为类方法,(也可以定义为实例方法)
调用
#1.通过类对象调用
类名.方法名()#不需要给cls传参,python解释器自动传递
#2.通过实例对象调用
实例.方法名()#不许要给cls传参,python解释其回自动传递
import random class Game(): top_score = 0 @staticmethod def show_help(): print('这是游戏的帮助信息') @staticmethod def show_top_score(): print(f'游戏最高分{Game.top_score}') @classmethod def start_game(cls): score = random.randint(10, 100) print(f'本次游戏得分为:', score) if score > cls.top_score: cls.top_score = score else: pass xm = Game() xm.start_game() xm.show_top_score() xm.start_game() xm.show_top_score()
补充
哈希(hash):是一个算法,可以对数据产生一个唯一的值(指纹)
is 可以用来判断两个对象是不是同一个对象,即两个对象的引用是否相同
a is b id(a)==id(b)
面试题可能回问:is 和 ==是否相同
==只判断是否相同 而is判断引用是否相同
文件
计算机的文件 就是存贮在某种长期存储设备上的一段数据
作用:将数据长期保存下来,在需要时使用
-文本文件
--能够使用记事本软件打开(能够使用记事本转换为文字)
txt ,md ,py,html,css,js,json
文件操作
1.打开文件
def open(file, mode='r', buffering=None, encoding=None): # known special case of open
参数file:是要打开的文件,类型是字符串,文件的路径可以是相对路径,也可以是绝对路径,建议写相对路径
》参数mode:默认参数(缺省参数),表示的是打开文件的方式
》r:read 只读打开
》w :write 只写打开
》a:append 追加打开,在文件的末尾写入内容
》参数 encoding:编码方式,(文字和二进制如何进行转换的)
》gbk:将一个汉字转换为2个字节二进制
》utf-8:常用将一个汉字转换为3个字节的二进制
》返回值:返回的是文件对象,后续对文件的操作,都需要这个对象
2.读或者写文件
向文件中写入指定的内容
前提:文件的打开方式是w或者a
文件对象.write('写入文件的内容')
读文件
将文件中的内容读取出来
前提:文件的打开方式是 r
文件对象.read(n)
#参数n表示读取多少个字符,一般不写,表示读取全部内容
#返回值:读取到的文件内容,类型 字符串
3.关闭文件
文件对象.close()
使用with open 打开文件
with open()打开文件的好处:不用自己去书写关闭文件的代码,会自动进行关闭
with open(file,mode,‘encoding=‘utf-8’’)as 变量:
按行读取文件
按行读取文件:一次读取一行内容
文件对象.readline()
json文件的处理
json文件也是一个文本文件,就可以直接使用read()和write()方法去操作文件,只是使用这两个方法,不方便,所以对json文件有自己独特的读取和写入方法
常用在 在做测试的时候,将测试数据定义为json文件格式,使用代码读取json文件, 嫉妒去测试数据,进行传参
json文件的语法
1.json文件的后缀是.json
2.json中主要数据类型为 对象({}累次python中的字典)和数组([],类似python中的列表),对象和数组可以相互嵌套
3.一个json文件是一个对象或者数组(即json文件的最外层要么是一个{},要么是一个数组[])
4.json中的对象是由键值对组成的,每个数据之间使用逗号隔开,但最后一个数据后面不要写逗号
5.json中的字符串 必须使用双引号
6.json中的数据类型
数字类型---》int float
string字符串--》str
布尔类型 true,false----》 Ture ,False
null---》None
json的写入
步骤
1.导包 import josn
2.写(w)方式打开文件
3.写入
json.dump(Python 中的数据类型,文件对象)
读取
json.load()
异常
程序停止执行并且提示错误信息 这个动作,抛出异常(raise关键字)
捕获异常:程序遇到异常,默认动作是终止代码程序的执行,遇见异常后,可以使用捕获异常,让代码继续运行,不会终止运行
捕获异常
基本语法
try:
书写可能发生异常的代码
except:#任何类型的异常都能捕获
发生了异常执行的代码
try:
书写可能发生异常的代码
except 异常类型:#只能捕获指定类型的异常,如果不是这个异常,还是会报错
发生了异常执行的代码
捕获多个指定类型异常
try:
书写可能发生异常的代码
except 异常类型1:
发生了异常1执行的代码
except 异常类型2:
发生了异常2执行的代码
except......:
try: num = input('请输入数字:') num = int(num) print(num) a = 10 / num print(f'{a}') except ValueError: print('类型错误,请输入正确的数字') except ZeroDivisionError: print('除数不能为0') #请输入数字:aaa #,请输入正确的数字
完整异常捕获
try:
书写可能发生异常的代码
except 异常类型1:
发生了异常1执行的代码
except Exception as 变量:
#Exception 是常见异常的父类,这里书写Exception,可以捕获常见的 所有异常,as 变量,这个变量是个异常类的对象,print(变量)可以打印异常信息
发生其他类型的异常,执行代码
else:
没有发生异常执行的代码
finally:
不管有没有发生异常,都会执行的代码
异常传递
模块和包
1.python源代码文件就是一个模块
2.模块中定义的变量 函数 类,都可以让别人使用,可以使用别人定义的
3.想要使用别人模块中的内容工具(变量,类,函数),必须先导入模块才能使用
4.我们自己写的代码,想要作为模块使用,代码的名字需要满足标识符的规则(由数字字母下换线开头,不能用数字开头)
导入模块的语法
方式一
import 模块名
#使用模块中的内容
模块名.工具名
方式二
from 模块名 import 工具名
工具名 #如果是函数和类需要加括号
举例
form random import randint
randint(a,b)
方式三(基本不用)
form 模块名 import * #将模块中所有的内容都导入
对于导入的模块和工具可以使用as 关键字给其起别名
注意:如果起别名,原来的名字就不能用了,只能使用别名
模块的查找顺序
在导入模块的时候,会在当前目录中找模块,如果找到,就直接使用,如果没有找到回去系统的目录中进行查找,找到,直接使用。
没有找到,报错
注意点:定义代码文件的时候,你的代码名字不能和你要导入的模块名字相同
__name__的作用
1.每个代码文件都是一个模块
2.在导入模块的时候,会执行模块中的内容
3.__name__变量
1).__name__变量是python解释器自动维护的变量
2)__name__变量,如果代码直接运行,值是‘’__main__‘’
3)如果__name__变量,如果代码是被导入执行,值是模块名(即代码文件名)
在被导入时,不想被执行的代码可以写在 if __name__=="__main__":代码缩进中
:包(pacakage)
在python中,包是一个目录,只不过在这个目录,只不过在这个目录存在一个文件__init__.py(可以是空)
功能相近或者相似的代码放在一起
在python中使用的时候,不需要区别包和模块,使用方式都是一样的
random 模块
json 包(目录)
1.import 包名
2.alt 回车 快捷导入
UnitTest框架
unittest核心要素(的组成)
1.TestCase(最核心的模块)
TestCase(测试用例),注意这个测试用例是unittest框架的组成部分,不是手工和自动化中我们所说的用例
主要作用:每个TestCase(测试用例)都是一个代码文件,在这个代码文件中来书写真正的用例代码
2.TestSuit
TestSuit(测试套件),用来管理 组装(打包)多个TestCase(测试用例)的
3.TestRunner
TestRunner(测试执行,测试运行),用来执行TestSuit(测试套件)的
4.TestLoader
TestLoader(测试加载),功能是对TestSuit(测试套件)功能的补充,用来管理 组装(打包)多个TestCase(测试用例)的
5.Fixture
测试夹具,作用:书写在TestCase(测试用例)代码中的,是一种代码结构,在每个方法执行前后都会执行的内容
TestCase
步骤:1.导包(Unittest)2.自定义测试类 3.在测试中书写测试方法 4.执行用例
import unittest class TestDemo(unittest.TestCase): def test_method1(self): print('测试方法1') def test_method2(self): print('测试方法2') #将光标放在类名后面就会执行后面的所有方法 #将光标放在方法后只执行这个方法
常见问题
1.文件名必须是字母数字下划线,不能以数字开头
2.文件是python进行运行的,必须修改环境变量python unittest
3.测试方法中不是以test_开头的,或者单词写错了
TestSuite&TestRunner
TestSuite(测试套件):管理 打包 组装 TestCase(测试用例)文件的
TestRuner:执行TestSuite(套件)
步骤
1.导包(unittest)
2.实例化(创建对象)套件对象
3.使用套件对象添加用例方法
4.实例化运行对象
5.使用运行对象去执行套件对象
代码
TestSuit(测试套件):用来管理多个TestSuit(测试用例)的
#导包
import unittest
from news import testDemo1
#实例化(创建对象)套件对象
suite = unittest.TestSuite()
#使用套件对象添加 套件对象.addTest(类名(方法)
suite.addTest(testDemo1('test_method1'))
suite.addTest(testDemo1('test_method2'))
#实例化运行对象
runner = unittest.TextTestRunner()
#使用运行对象去执行套件对象
#运行对象.run(套件对象)
runner.run(suite)
#导包
import unittest
from news import testDemo1
#实例化(创建对象)套件对象
suite = unittest.TestSuite()
#使用套件对象添加 第二种方法套件对象.addTest(unittest.makeSuite(类名))
suite.addTest(unittest.makeSuite(testDemo1))
#实例化运行对象
runner = unittest.TextTestRunner()
#使用运行对象去执行套件对象
#运行对象.run(套件对象)
runner.run(suite)
TestLoader(测试加载)
TestLoader(测试加载),作用和Testsuite的作用是一样的,对TestSuite功能的补充,用来组装测试用例的
比如:如果TestCase的代码文件有很多,(10,20,30)
使用步骤
1.导包
2.实例化测试加载对象并添加用例 ---》得到的是suite对象
3.实例化运行对象
4.运行对象执行套件
#TestLoader的使用
import unittest
unittest.TestLoader().discover(‘用例所在的路径(相对)’,‘用例代码文件名’)
suite=unittest.TestLoader().discover(‘./case’,‘hm*.py’)
suite=unittest.TestLoader().discover(‘./case’,*test*.py’)
#实例化运行对象并且执行
unittest.TextTestRunner().run(suite)
Fixture(测试夹具)
在某些特定的情况下回自动执行
方法级别(掌握)
#方法执行之前
def setup(self):
每个方法执行之前都会执行
#方法执行之后
def teardown(self):
每个方法执行后都会执行
pass
类级别在每个测试类中所有方法执行前后都会调用的结构(在整个类中 ,执行之前执行之后个一次)
#类中所有方法之前
@classmethod
def setupClass(cls):
pass
#勒种所有方法之后
@classmethod
def teardwon(cls):
pass
模块级别(了解)
#模块级别的需要写在类的外边直接定义函数即可
#代码文件之前
def setupModule():
pass
#代码文件之后
def teardownModule():
pass
方法级别和类级别的 前后的方法,不需要同时出现,根据用例代码的需要自行选择使用
断言
让程序代替人工自动的判断预期结果和实际结果是否相符
断言的结果有两种:
》True,用例通过
》Flase,代码抛出异常,用例不通过
asserEqual
asserEqual(预期结果,实际结果)#判断预期结果和实际结果是否相等
1.如果相等,用例通过
2.如果不相等,用例不通过,抛出异常
assertln
assertlin(预期结果,实际结果) #预期结果是否包含在实际结果中
1.包含,用例通过
2.不包含,用例不通过,抛出异常
参数化
参数化在测试方法中,使用变量来代替具体的测试数据,然后用传参的方法将测试数据传递给方法的变量
好处:相似的代码不需要多次书写
工作场景:
1.测试数据一般存放在json文件中
2.使用代码读取json文件,提取我们想要的数据 --》[(),()] or [[],[]]
安装插件
-联网安装(在cmd窗口)
pip install parameterized
可以在pycha终端中下载
参数化代码
1.导包
2.定义测试类
3.书写测试方法(用到的测试数据使用变量代替)
4.组织测试数据并传参
跳过
#直接将测试函数标记跳过
@unittest.skip(‘跳过原因’)
@unittest.skipIf(跳过条件,‘跳过’)
import unittest version=29 class TestDemo(unittest.TestCase): @unittest.skip('没原因就跳过') def test_1(self): print('测试方法一') @unittest.skipIf(version>=30,'版本大于等于30,不用测试') def test_2(self): print('测试方法二') def test_3(self): print('测试方法三')