python
常用快捷键
ctrl + alt + s :打开软件设置 ctrl +d : 复制当前行代码 shift + alt +上\下:将当前行代码上移或下移 crtl + shift +f10 :运行当前代码文件 shift + f6 :重命名文件 ctrl+a:全选 ctrl+c\v\x:复制、粘贴、剪切 ctrl+f:搜索
基础知识
字面量
在代码中被写下来的固定值。
值的类型
数字 整数,浮点数,复数,布尔(true 1 false 0)
字符串
列表 有序可变序列
元组 有序不可变序列
集合 无序不重复集合
字典 无序key-value集合
注释
单行 #注释内容 建议#与注释内容之间有一个空格
多行 用三引号引用 “”“内容”“”
数据类型
查看数据的类型
type(被查看类型的数据)
t1=type(("hello")) print(t1)
也可以查看变量中存储的数据类型
money=50 t1=type(50) print(t1)
变量没有类型,有类型的是变量中的数据
转换
转换类型但是不会破坏数据即内容
t1=str(12.34) print(type(t1),t1)
所有类型都可以转换成字符串,但是字符串要转化为其他类型的话必须引号里面都是数字才可以
标识符
用户在编程时所使用的一系列名字,用于给变量,类,方法等命名。
只允许出现英文中文(不推荐)数字(不可用在开头)和下划线,区分大小写,不能用关键字
变量命名规范:见名知意,多个单词组合变量名,要使用下划线做分隔,英文字母全部小写
运算符
// 取整除即返回商的整数部分 9//2=4 9.0//2.0=4.0
% 取余
** 指数
字符串
单引号定义: name='aaa'
双引号定义:name="aaa"
三引号定义:name="""aaa"''"" (支持换行操作)
引号的套用:单引号定义法可以内含双引号,双引号定义法可以内含单引号,也可以用转义字符(\)将引号接触效用,变成普通字符串
字符串拼接
无法用加号和整数浮点数等拼接
name = "黑马程序员" message = "学IT就来%s" % name print(message)
其中的,%s ·% 表示:我要占位 ·s 表示:将变量变成字符串放入占位的地方 所以,综合起来的意思就是:我先占个位置,等一会有个变量过来,我把它变成字符串放到占位的位置
数字也可以用%s占位
其他类型的占位
%s 变为字符串 %d 变为整数 %f 变为浮点型
快速书写
f“内容{变量}”
name="zzz" p1=20.3 p2=2000 print(f"我是{name},有{p1},还有{p2}")
print("1*1=%d" %(1*1)) print("'aaa'的字符串类型是%s" %type('aaa'))
不需要变量时候直接写格式化表达式也可。
数字精度控制
用辅助符号“m.n”来控制数据的宽度和精度
m:控制宽度,要求是数字(很少使用),设置的宽度小于数字自身不生效
.n:控制小数点精度,要求是数字,会进行小数的四舍五入
数据输入
print("请说出你是谁") name=input() # input()=name报错 print("你是%s" % name)
input无论写入什么数据,都被当作字符串
input(提示信息)
name=input("请说出你是谁") # input()=name报错 print("你是%s" % name)
如果需要其他类型的,可以通过数据转换
num=input("输出数字") num=int(num) print("shuzi", type(num))
print输出不换行
print("Hello") #print输出换行 print("Hello") print("Hello",end='') #print输出不换行 print("Hello",end='')
制表符
\t,效果相当于在键盘上摁tab键,它可以让多行字符串进行对齐
判断语句
布尔类型
定义变量存储布尔类型数据:
变量名称=布尔类型字面量
也可以通过比较运算符进行内容比较得到
b1=12 b2=10 print(f"是否相等:{b1==b2}")
if语句
基础语句
if 要判断的条件:
(有四个空格,通过四个空格判断归属) 条件成立时,要做的事情
age=4 print(f"今年{age}") if age>18: print("我成年了") print("hhh") print("真棒啊")
age=input("年龄") print(f"今年{age}") age=int(age) if age>18: print("我成年了") print("hhh") print("真棒啊")
要注意类型的转换
if else
age=int(input("年龄")) if age>18: print("我成年了") print("hhh") else: print("真棒啊")
else后不需要加执行的条件,它执行的语句同样需要前面有四格缩进
if elif else
print("欢迎来到黑马动物园") # 判断是互斥且有顺序的,满足1则不会进行2和3,都不满足则进入else,else也 可省略不写,效果等同于3个独立的if判断 if int(input("请输入您的身高:"))<120: print("没,免费玩") elifint(input("请输入等级")) >3: print("免费玩") elif int(input("输入周几"))==1: print("免费玩") else: print("买票") print("祝您愉快")
判断语句的嵌套
if 条件1:
满足条件1 做的事情1
满足条件2 做的事情2
if 条件2:
满足条件2 做的事情1
满足条件2 做的事情2
嵌套的关键是空格缩进,通过空格缩进来决定层次关系
if int(input("你的身高:"))>120: print("已成年,请购票") print("如果是VIP3可免费") if int(input("你的VIP等级是:"))>3: print("欢迎您") print("不用买门票") else: print("请购票") print("欢迎您的到来")
import random # 猜数字,随机数 num=random.randint(1,10) gnum=int(input("输入一个数字")) if gnum==num: print("恭喜你,一次就猜中了") else: print("猜错了,你还有两次机会") if gnum > num: print("猜大了") else: print("猜小了") gnum = int(input("再次输入一个数字")) if gnum==num: print("恭喜你,第二次猜对了") else: print("又错了,只有一次机会了") if gnum>num: print("猜大了") else: print("猜小了") gnum = int(input("最后一次输入一个数字")) if gnum==num: print("恭喜你,最后一次猜对了") else: print("又错了,没有机会了")
循环语句
while循环
i=0 # 也有缩进 while i<100: print("gogogo") i+=1
import random #猜数字进阶 num=random.randint(1,100) i=0 flag=True while flag: gnum = int(input("请输入一个数字")) i += 1 if gnum==num: print("猜对了") flag=False else: if gnum>num: print("猜错了") print("猜大了") else: print("猜错了") print("猜小了") print(f"终于猜对了,你猜了{i}次")
while循环的嵌套
i=1 while i<=100: print(f"今天是第{i}天表白") j=1 while j<=10: print(f"送给小妹第{j}朵花") j+=1 i+=1 print(f"第{i-1}天表白成功")
i=1 //九九乘法表 while i<=9: j=1 while j<=i: print(f"{j}*{i}={j*i}\t",end='') j+=1 i+=1 print()
for循环
是一种轮询机制,对一批内容进行逐个处理
***for 临时变量 in 待处理数据集:***
***循环满足条件时执行的代码***
name="zhang" for x in name: #将name的内容挨个取出赋值给x这个临时变量 print(x,end='')
无法定义循环条件
range语句
本质上是生成数字序列
range(num)
获取一个从0开始,到num结束的数字序列(不包含num本身)
range(num1,num2)
获取一个从num1开始到num2结束的数字序列,不包含num2
range(num1,num2,step)
获取一个从num1开始到num2结束的数字序列,不包含num2,数字之间的步长,以step为标准(step默认为1)
range(5,9,2)获取的数字是【5,7,9】
for循环的临时变量,在规范上来讲是在循环内起作用
嵌套
i=1 for i in range(1,101): print(f"喜欢小美的第{i}天") j=1 for j in range(1,11): print(f"送给小美第{j}朵") print(f"第{i}天,表白成功")
for i in range(1,10): //九九乘法表 for j in range(1,i+1): print(f"{j}*{i}={j*i}\t",end='') print()
continue
用于中断本次循环,直接进入下一次循环
它可以用于for循环和while循环,效果是一样的
for i in range(1,100) 语句1 continue 语句2
此时语句2 不执行
break
直接结束循环
在for循环和while循环中都可以使用
函数
是组织好的可以重复使用的用来实现特定功能的代码块
好处:随时随地重复利用
提高代码复用性,减少重复代码,提高效率
定义
def 函数名(传入参数): 函数体 return 返回值
调用:函数名(参数)
如果参数和返回值不需要的话可以省略
函数必须先定义后使用
参数
传入参数功能:在函数计算的时候,接受外部(调用时)的数据
def add(a,b): #形参,表示函数声明将要使用两个参数,用,分隔开 result=a+b print(result) add(2,5)#函数调用,是实参,表示函数执行时真正使用的参数值,传入的时候要按照顺序,用,分隔开
返回值
定义
def 函数名(传入参数): 函数体 return 返回值 变量=函数(参数)
None类型
如果没有写返回数据其实函数也是有返回值的
函数返None时表示这个函数返回没有什么意义,其类型为<class 'NoneType'>
return None效果等同于不写return
应用场景
1.函数无返回值
2.在if语句中None等同于False
def check(age): if age>18: return "Success" return None result=check(34) if not result: print("未成年")
3.用在声明无内容的变量上
定义变量,暂时不需要变量有具体值,可用None替代
name=None
多返回值
按照返回值的顺序,写对应顺序的多个变量接收即可
变量之间用逗号隔开
支持不同类型的数据return
def c(): return1,2 x,y=c() print(x)#结果1 print(y)#结果2
说明文档
用于辅助理解函数,写在函数体之前,鼠标在调用时悬浮着的时候会展示出写的说明文档
def check(x,y): """ 函数说明 :param x:形参x的说明 :param y:形参y的说明 :return:返回值说明 """ 函数体 return 返回值
嵌套
def a(): print("1") def b(): print("2") a() print("3") b()
变量作用域
是指变量的作用范围,分为局部变量和全局变量
局部变量
定义在函数体内部的变量,只在函数内部生效
在函数运行时临时保存数据,运行完以后立刻销毁局部变量
全局变量
在函数体内外都能生效的变量
global关键字
在函数内部声明变量为全局变量
num=20 def a(): print(num) def b(): global num #如果没有global这行,则最后print(num)的值为20 num=50 print(num) a() b() print(num)
money=5000000 #取款练习 name=None name=input("请输入用户名") def search(show_header): if show_header: print(f"{name}你好,你的余额有{money}") def changejia(num): global money money+=num print(f"{name}你好,存款{num},你的余额有{money}") def changejian(num): global money money -= num print(f"{name}你好,取款{num},你的余额有{money}") def main(): print(f"你好{name},欢迎来到ATM,请选择:") print("查钱:1") print("冲钱:2") print("提钱:3") print("退出:4") return input("请输入选择") while True: keyboard_input=main() if keyboard_input=="1": search(True) continue elif keyboard_input=="2": num=int(input("请输入存钱数")) changejia(num) continue elif keyboard_input == "3": num = int(input("请取出钱数")) changejian(num) continue else: print("退出") break
多种传参方式
位置参数
调用函数时根据函数定义的参数位置来传递参数
def n(name,age,gender): print(f"{name},{age},{gender}") n("a",2,"男")
传递的参数和定义的参数的顺序及个数必须一致
关键字参数
函数调用时通过“键=值”形式传递参数
作用: 可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求
函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序
def n(name,age,gender): print(f"{name},{age},{gender}") n(age=2,name="n",gender="男")
不定长参数
不定长参数也叫可变参数. 用于不确定调用的时候会传递多少个参数(不传参也可以)的场景
作用: 当调用函数时不确定参数个数时, 可以使用不定长参数
不定长参数的类型:
①位置传递
传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递
def m(*args): print(args) m("yo") m("yo",22)
②关键字传递
参数是“键=值”形式的形式的情况下, 所有的“键=值”都会被kwargs接受, 同时会根据“键=值”组成字典
def m(**kwargs): print(kwargs) m(name="yo",age=22,id=1)
缺省参数
缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
作用: 当调用函数时没有传递参数, 就会使用默认是用缺省参数对应的值
函数调用时,如果为缺省参数传值则修改默认参数值, 否则使用这个默认值
def n(name,age,gender="男"): print(f"{name},{age},{gender}") n("a",2) n("c",22,"女")
匿名函数
函数作为参数传递
函数本身是可以作为参数,传入另一个函数中进行使用的
将函数传入的作用在于:传入计算逻辑,而非传入数据。
lambda匿名函数
函数的定义中
def关键字,可以定义带有名称的函数
lambda关键字,可以定义匿名函数(无名称)
有名称的函数,可以基于名称重复使用。
无名称的匿名函数,只可临时使用一次。
定义语法
lambda 传入参数:函数体(一行代码)
lambda 是关键字,表示定义匿名函数
传入参数表示匿名函数的形式参数,如:x, y 表示接收2个形式参数
函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码
def test(compute): result=compute(1,2) print(result) test(lambda x,y:x+y) #结果为3
数据容器
基础知识
一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素,每个元素可以是任意类型的数据,比如说字符串数字布尔等
分类
分为列表,元组,字符串,集合,字典
list
有序存储,允许重复数字存在,可以有不同类型
# 变量的定义 变量名称=[元素1,元素2,元素3.......] # 定义空列表 变量名称=[] 变量名称=list()
列表中的每一个数据称为元素
列表可一次存储多个数据,且可以为不同的数据类型,支持嵌套
list=[[1,2,3],[4,5,6]]
下标索引
常用操作方法
查询指定元素
列表.index(元素)
查找指定元素在列表的下表,如果找不到,报错ValueError
index就是列表对象(变量)内置的方法(函数)
修改特定位置(索引)的元素值
列表[下标]=值
插入元素
列表.insert(下标,元素),在指定的下标位置,插入指定的元素
追加元素
列表.append(元素),将指定元素追加到列表的尾部
列表.extend(其他数据容器),将其他数据容器的内容取出,依次追加到列表尾部
s1=[1,2,3] s2.extend([4,5,6])
删除元素
语法1:del 列表[下标]
语法2:列表.pop(下标),它还可以把删掉的元素作为返回值得到
删除匹配项
删除的是某元素在列表中的第一个匹配项
列表.remove(元素)
清空列表内容
列表.clear()
统计某元素
统计某元素在列表内的数量
列表.count(元素)
统计列表元素
len(列表)
print(len(list))
遍历
while
index=0 while index<len(列表): 元素=列表[index] insex+=1
for
for 临时变量 in 数据容器: 对临时变量进行处理
list=[21,25,21,23,22,20] for e in list: print(e)
对比
在循环控制上:while循环可以自定循环条件,并自行控制
for循环不可以自定循环条件,只可以一个个从容器内取出数据
在无限循环上:while循环可以通过条件控制做到无限循环
for循环理论上不可以,因为被遍历的容器容量不是无限的
在使用场景上:while循环适用于任何想要循环的场景
for循环适用于遍历数据容器的场景或简单的固定次数循环场景
tuple(元组)
和列表一样,可以封装多个,不同类型的元素在内
但是元组一旦定义完成,就不可以修改,元组的数据可以是不同的数据类型
变量名称=(元素,元素...元素) #定义空元组 变量名称=()------法一 变量名称=tuple()---法二
如果元组内嵌套了list,则可以修改list的内容
t1=(1,2,[3,4]) t1[2][1]=5 print(t1)
t1=('张三',11,['football','music']) del t1[2][0] #删除元素 print(t1) t1[2].append('coding') #增加元素 print(t1)
如果定义一个元素的元组,这个数据后面要加一个逗号
t2=('Hello',)
元组也支持嵌套,支持下标索引
常用操作方法
index()
查找某个数据,如果数据存在返回对应的下标,否则报错
count()
统计某个数据在当前元组出现的次数
len(元组)
统计元组内元素个数
str(字符串)
是无法修改的数据容器,也可以通过下标来访问
常用操作方法
字符串的替换
字符串.replace(字符串1,字符串2)
将字符串内的全部内容:字符串1,替换为字符串2
这不是在修改字符串本身,而是得到了一个新字符串
字符串分割
字符串.split(分隔符字符串)
按照指定的分隔符字符串,将字符串分割为多个字符串,并存入列表对象中
字符串本身不变,而是得到了一个列表对象
s1="ddd aaa vvv ccc" l1=s1.split(" ") print(l1)
字符串规整
去前后空格
字符串.strip()
去前后指定字符串
字符串.strip(字符串)
li="sjosw 21 xjios12" print(li.strip("12")) #传入的是12其实是1和2都会被移除,是按照单个字符串的
统计出现次数
str="qwertyteq" count=str.count("q")
统计长度
len(字符串)
数据容器的切片
序列:内容连续有序,可以使用下标索引的一类数据容器
切片:从一个序列中取出一个子序列
语法:序列[起始下标:结束下标:步长]
表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列:起始下标表示从何处开始,可以留空,留空视作从头开始
结束下标(不含)表示何处结束,可以留空,留空视作截取到结尾
步长表示:依次取元素的间隔
步长1表示,一个个取元素
步长2表示,每次跳过1个元素取
步长N表示,每次跳过N-1个元素取
步长为负数表示,反向取(注意,起始下标和结束下标也要反向标记)
注意,此操作不会影响序列本身,而是会得到一个新的序列(列表、元组、字符串)
切片
数列的常用操作
my_list = [1, 2, 3, 4, 5] new_list = my_list[1:4] # 下标1开始,下标4(不含)结束,步长1 print(new_list) # 结果:[2, 3, 4]
my_tuple = (1, 2, 3, 4, 5) new_tuple = my_tuple[:] # 从头开始,到最后结束,步长1 print(new_tuple) # 结果:(1, 2, 3, 4, 5)
my_list = [1, 2, 3, 4, 5] new_list = my_list[::2] # 从头开始,到最后结束,步长2 print(new_list) # 结果:[1, 3, 5]
my_str = "12345" new_str = my_str[:4:2] # 从头开始,到下标4(不含)结束,步长2 print(new_str) # 结果:"13"
my_str = "12345" new_str = my_str[::-1] # 从头(最后)开始,到尾结束,步长-1(倒序) print(new_str) # 结果:"54321" my_list = [1, 2, 3, 4, 5] new_list = my_list[3:1:-1] # 从下标3开始,到下标1(不含)结束,步长-1(倒序) print(new_list) # 结果:[4, 3] my_tuple = (1, 2, 3, 4, 5) new_tuple = my_tuple[:1:-2] # 从头(最后)开始,到下标1(不含)结束,步长-2(倒序) print(new_tuple) # 结果:(5, 3)
这个操作对列表、元组、字符串是通用的
同时非常灵活,根据需求,起始位置,结束位置,步长(正反序)都是可以自行控制的
s1="nxwdnxj wodn xm" s2=s1[::-1][2:4] print(s2)
set(集合)
不支持元素的重复(自带去重功能)、并且内容无序,不支持下标索引访问
因为要对元素做去重处理所以无法保证顺序和创建的时候一致
#定义集合字面量 {元素,元素,......,元素} #定义集合变量 变量名称={元素,元素,......,元素} #定义空集合 变量名称=set()
修改
添加
语法:集合.add(元素)
将指定元素,添加到集合内 结果:集合本身被修改,添加了新元素
移除
语法:集合.remove(元素)
将指定元素,从集合内移除 结果:集合本身被修改,移除了元素
随机取出元素
语法:集合.pop()
功能,从集合中随机取出一个元素 结果:会得到一个元素的结果。同时集合本身被修改,元素被移除
清空
语法:集合.clear()
功能,清空集合 结果:集合本身被清空
取出2个集合的差集
语法:集合1.difference(集合2)
功能:取出集合1和集合2的差集(集合1有而集合2没有的) 结果:得到一个新集合,集合1和集合2不变
消除2个集合的差集
语法:集合1.difference_update(集合2)
功能:对比集合1和集合2,在集合1内,删除和集合2相同的元素。 结果:集合1被修改,集合2不变
2个集合合并
语法:集合1.union(集合2)
功能:将集合1和集合2组合成新集合 结果:得到新集合,集合1和集合2不变
长度
查看集合的元素数量
语法:len(集合)
功能:统计集合内有多少元素 结果:得到一个整数结果
集合同样支持使用for循环遍历,不支持下标索引,所以也就不支持使用while循环。
dict
Key:Value 通过Key找到value
定义
#定义字典字面量 {key:value,key:value,key:value,......} #定义字典变量 m={key:value,key:value,key:value,......} #定义空字典 n={}//方式1 m=dict()//方式2
字典的定义,同样使用{},不过存储的元素是一个个的:键值对,
使用{}存储原始,每一个元素是一个键值对
每一个键值对包含Key和Value(用冒号分隔)
键值对之间使用逗号分隔
Key和Value可以是任意类型的数据(key不可为字典)
Key不可重复,重复会对原有数据覆盖
不可以使用下标索引
但是可以通过Key值来取得对应的Value
字典的Key和Value可以是任意数据类型(Key不可为字典)
字典是可以嵌套的
常用操作
新增元素
语法:字典[Key] = Value
结果:字典被修改,新增了元素
更改元素
语法:字典[Key] = Value
结果:字典被修改,元素被更新
注意:字典Key不可以重复,所以对已存在的Key执行上述操作,就是更新Value值
删除元素
语法:字典.pop(Key)
结果:获得指定Key的Value,同时字典被修改,指定Key的数据被删除
清空字典
语法:字典.clear()
结果:字典被修改,元素被清空
获取全部的key
语法:字典.keys()
结果:得到字典中的全部Key
遍历字典
语法:for key in 字典.keys()
注意:字典不支持下标索引,所以同样不可以用while循环遍历
计算字典内的全部元素(键值对)数量
语法:len(字典)
结果:得到一个整数,表示字典内元素(键值对)的数量
总结对比
分类
数据容器可以从以下视角进行简单的分类:
是否支持下标索引
支持:列表、元组、字符串 - 序列类型
不支持:集合、字典 - 非序列类型
是否支持重复元素
支持:列表、元组、字符串 - 序列类型
不支持:集合、字典 - 非序列类型
是否可以修改
支持:列表、集合、字典
不支持:元组、字符串
** ** | 列表 | 元组 | 字符串 | 集合 | 字典 |
---|---|---|---|---|---|
元素数量 | 支持多个 | 支持多个 | 支持多个 | 支持多个 | 支持多个 |
元素类型 | 任意 | 任意 | 仅字符 | 任意 | Key:ValueKey:除字典外任意类型Value:任意类型 |
下标索引 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
重复元素 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
可修改性 | 支持 | 不支持 | 不支持 | 支持 | 支持 |
数据有序 | 是 | 是 | 是 | 否 | 否 |
使用场景 | 可修改、可重复的一批数据记录场景 | 不可修改、可重复的一批数据记录场景 | 一串字符的记录场景 | 不可重复的数据记录场景 | 以Key检索Value的数据记录场景 |
通用操作
首先,在遍历上:5类数据容器都支持for循环遍历列表
元组、字符串支持while循环,集合、字典不支持(无法下标索引)
尽管遍历的形式各有不同,但是,它们都支持遍历操作。
max(容器)
统计容器的最大元素
my_list = [1, 2, 3] my_tuple = (1, 2, 3, 4, 5) my_str = "itiheima" print(max(my_list)) # 结果3 print(max(my_tuple)) # 结果5 print(max(my_str)) # 结果t
min(容器)
统计容器的最小元素
my_list = [1, 2, 3] my_tuple = (1, 2, 3, 4, 5) my_str = "itiheima" print(min(my_list)) # 结果1 print(min(my_tuple)) # 结果1 print(min(my_str)) # 结果a
list(容器)
将给定容器转换为列表
tuple(容器)
将给定容器转换为元组
str(容器)
将给定容器转换为字符串
set(容器)
将给定容器转换为集合
sorted(容器, [reverse=True])
将给定容器进行排序注意,排序后都会得到列表(list)对象。
文件操作
文件的编码
编码就是一种规则集合,记录了内容和二进制间进行相互转换的逻辑。
编码有许多中,我们最常用的是UTF-8编码
为什么需要使用编码?
计算机只认识0和1,所以需要将内容翻译成0和1才能保存在计算机中。同时也需要编码, 将计算机保存的0和1,反向翻译回可以识别的内容
文件的读取
open()打开函数
在Python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件(写入的是内存中,如果要写入硬盘中即文档里有写入内容要调用flush方法)
语法
open(name, mode, encoding)
name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)
mode:设置打开文件的模式(访问模式):只读、写入、追加等
encoding:编码格式(推荐使用UTF-8)
f = open('python.txt', 'r', encoding=”UTF-8) # encoding的顺序不是第三位,所以不能用位置参数,用关键字参数直接指定
此时的f
是open
函数的文件对象,对象是Python中一种特殊的数据类型,拥有属性和方法,可以使用对象.属性或对象.方法对其进行访问
mode常用的三种基础访问模式
模式 | 描述 |
---|---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,原有内容会被删除。如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
读操作相关方法
read()方法
文件对象.read(num)
num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。
readlines()方法
f = open('python.txt') content = f.readlines() # ['hello world\n', 'abcdefg\n', 'aaa\n', 'bbb\n', 'ccc'] print(content) # 关闭文件 f.close()
readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
readline()方法
次读取一行内容
f = open('python.txt') content = f.readline() print(f'第一行:{content}') content = f.readline() print(f'第二行:{content}') # 关闭文件 f.close()
for循环读取文件行
for line in open("python.txt", "r"): print(line) # 每一个line临时变量,就记录了文件的一行数据
close() 关闭文件对象
f = open("python.txt", "r") f.close() # 最后通过close,关闭文件对象,也就是关闭对文件的占用 # 如果不调用close,同时程序没有停止运行,那么这个文件将一直被Python程序占用。
with open
with open("python.txt", "r") as f: f.readlines() # 通过在with open的语句块中对文件进行操作 # 可以在操作完成后自动关闭close文件,避免遗忘掉close方法
文件的写入
# 1. 打开文件 f = open('python.txt', 'w') # 2.文件写入 f.write('hello world') # 3. 内容刷新 f.flush()
直接调用write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区
当调用flush的时候,内容会真正写入文件
这样做是避免频繁的操作硬盘,导致效率下降(攒一堆,一次性写磁盘)
文件如果不存在,使用”w”模式,会创建新文件
文件如果存在,使用”w”模式,会将原有内容清空
关闭
.close
内置了flush功能
追加
# 1. 打开文件,通过a模式打开即可 f = open('python.txt', 'a') # 2.文件写入 f.write('hello world') # 3. 内容刷新 f.flush()
a模式,文件不存在会创建文件
a模式,文件存在会在最后,追加写入文件
可使用\n实现换行写出
异常
捕获异常
捕获异常的作用在于:提前假设某处会出现异常,做好提前准备,当真的出现异常的时候,可以有后续手段。
常规异常
try: 可能发生错误的代码 except: 如果出现异常执行的代码
指定异常
try: print(name) except NameError as e: print('name变量名称未定义错误')
① 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
② 一般try下方只放一行尝试执行的代码。
多个异常
当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的方式进行书写。
try: print(1/0) except (NameError, ZeroDivisionError): print('ZeroDivision错误...')
捕获异常并输出描述信息
try: print(num) except (NameError, ZeroDivisionError) as e: print(e)
捕获所有异常
try: print(name) except Exception as e: print(e)
异常else
else表示的是如果没有异常要执行的代码。
try: print(1) except Exception as e: print(e) else: print('我是else,是没有异常的时候执行的代码')
异常的finally
finally表示的是无论是否异常都要执行的代码,例如关闭文件。
try: f = open('test.txt', 'r') except Exception as e: f = open('test.txt', 'w') else: print('没有异常,真开心') finally: f.close()
异常的传递性
利用异常具有传递性的特点, 当我们想要保证程序不会因为异常崩溃的时候, 就可以在main函数中设置异常捕获, 由于无论在整个程序哪里发生异常, 最终都会传递到main函数中, 这样就可以确保所有的异常都会被捕获
模块
Python 模块(Module),是一个 Python 文件,以 .py 结尾. 模块能定义函数,类和变量,模块里也能包含可执行的代码
模块的作用: python中有很多各种不同的模块, 每一个模块都可以帮助我们快速的实现一些功能, 比如实现和时间相关的功能就可以使用time模块
我们可以认为一个模块就是一个工具包, 每一个工具包中都有各种不同的工具供我们使用进而实现各种不同的功能
大白话:模块就是一个Python文件,里面有类、函数、变量等,我们可以拿过来用(导入模块去使用)
导入方式
模块在使用前需要先导入
语法
[from 模块名] import [模块|类|变量|函数|*][as 别名]
常用的组合形式如:
import 模块名
from 模块名 import 类、变量、方法等
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名
import 模块名
import 模块名 import 模块名1,模块名2 模块名.功能名() # 导入时间模块 import time print("开始") # 让程序睡眠1秒(阻塞) time.sleep(1) print("结束")
from 模块名 import 类、变量、方法等
from 模块名 import 功能名 功能名() # 导入时间模块中的sleep方法 from time import sleep print("开始") # 让程序睡眠1秒(阻塞) sleep(1) print("结束")
from 模块名 import *
from 模块名 import * 功能名() # 导入时间模块中所有的方法 from time import * print("开始") # 让程序睡眠1秒(阻塞) sleep(1) print("结束")
as定义别名
# 模块定义别名 import 模块名 as 别名 # 功能定义别名 from 模块名 import 功能 as 别名 # 模块别名 import time as tt tt.sleep(2) print('hello') # 功能别名 from time import sleep as sl sl(2) print('hello')
自定义模板
每个Python文件都可以作为一个模块,模块的名字就是文件的名字. 也就是说自定义模块名必须要符合标识符命名规则
在实际开发中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,这个开发人员会自行在py文件中添加一些测试信息,例如,在my_module1.py文件中添加测试代码test(1,1)
def test(a, b): print(a + b) test(1, 1)
问题: 此时,无论是当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自动执行test
函数的调用
解决方案:
def test(a, b): print(a + b) # 只在当前文件中调用该函数,其他导入的文件内不符合该条件,则不执行test函数调用 if __name__ == '__main__': test (1, 1)
注意事项:当导入多个模块的时候,且模块内有同名功能. 当调用这个同名功能的时候,调用到的是后面导入的模块的功能
all
如果一个模块文件中有__all__
变量,当使用from xxx import *
导入时,只能导入这个列表中的元素
_all_=['test1'] 定义一个模块 def test1(): print("1") def test 2(): print("2")
此时导入包使用时只能用test1
包
包的作用: 当我们的模块文件越来越多时,包可以帮助我们管理这些模块, 包的作用就是包含多个模块,但包的本质依然是模块
导入包
方法一
import 包名.模块名
包名.模块名.目标
方法二
from 包名 import 模块名
模块名.目标
方法三
from 包名.模块名 import 目标
导入第三方包
我们知道,包可以包含一堆的Python模块,而每个模块又内含许多的功能。
所以,我们可以认为:一个包,就是一堆同类型功能的集合体。
在Python程序的生态中,有许多非常多的第三方包(非Python官方),可以极大的帮助我们提高开发效率,如:
科学计算中常用的:numpy包
数据分析中常用的:pandas包
大数据计算中常用的:pyspark、apache-flink包
图形可视化常用的:matplotlib、pyecharts
人工智能常用的:tensorflow等这些第三方的包,极大的丰富了Python的生态,提高了开发效率。
但是由于是第三方,所以Python没有内置,所以我们需要安装它们才可以导入使用哦。
如何安装?
方法1.在命令提示符内:
pip install 包名称
pip install -i
Simple Index 包名称
方法2.在PyCharm中安装
练习
def print_file_info(file_name): f=None try: f=open(file_name,"r",encoding="UTF-8") content=f.read() print("文件内容如下:") print(content) except Exception as e: print(f"出现异常,{e}") finally: if f: #如果变量是None,表示False,如果有任何内容,就是True f.close()
数据可视化
json
JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据
JSON本质上是一个带有特定格式的字符串
主要功能:json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互. 类似于:
国际通用语言-英语
中国56个民族不同地区的通用语言-普通话
数据格式
# json数据的格式可以是: {"name":"admin","age":18} # 也可以是: [{"name":"admin","age":18},{"name":"root","age":16},{"name":"张三","age":20}]
Python数据和Json数据的相互转化
# 导入json模块 import json # 准备符合格式json格式要求的python数据 data = [{"name": "老王", "age": 16}, {"name": "张三", "age": 20}] # 通过 json.dumps(data) 方法把python数据转化为了 json数据 data = json.dumps(data) # 通过 json.loads(data) 方法把json数据转化为了 python数据 data = json.loads(data)
如果有中文可以带上:ensure_ascii=False参数来确保中文正常转换
data = json.dumps(data,:ensure_ascii=False)
pyecharts模块
构建折线
from pyecharts.chars import Line #构建折线图对象 line=Line() #添加x轴数据 line.add_xaxis(["中国","美国","英国"]) #添加y轴数据 line.add_yaxis("GDP",[30,20,10]) #绘图 line.render()
全局配置
set_global_opts方法
title_opts=TitleOpts(title="GDP展示",pos_left="center",pos_bottom="1%") #离左侧的距离,离底部的距离
//练习 # 把不符合json数据格式的 "jsonp_1629350871167_29498(" 去掉 data = data.replace("jsonp_1629350871167_29498(", "") # 把不符合json数据格式的 ");" 去掉 data = data[:-2] # 数据格式符合json格式后,对数据进行转化 data = json.loads(data) # 获取日本的疫情数据 data = data["data"][0]['trend’] # x1_data存放日期数据 x1_data = data['updateDate’] # y1_data存放人数数据 y1_data = data['list'][0]["data"] # 获取2020年的数据 x1_data = data['updateDate'][:314] # 获取2020年的数据 y1_data = data['list'][0]["data"][:314]
init_opts | 对折线图初始化设置宽高 | init_opts=opts.InitOpts(width="1600px", height="800px") |
---|---|---|
.add_xaxis | 添加x轴数据 | .add_xaxis(列表) |
.add_yaxis | 添加y轴数据 |
.add_yaxis相关配置选项
配置项 | 作用 | 代码实例 |
---|---|---|
series_name | 设置图例名称 | series_name="美国确诊人数" |
y_axis | 输入y轴数据 | y_axis=["列表"] |
symbol_size | 设置点的大小 | symbol_size=10 |
label_opts | 标签设置项:不显示标签 | label_opts=opts.LabelOpts(is_show=False) |
linestyle_opts | 线条宽度和样式 | linestyle_opts=opts.LineStyleOpts(width=2) |
.set_global_opts全局配置选项
配置项 | 作用 | 代码实例 |
---|---|---|
title_opts | 设置图标题和位置 | title_opts=opts.TitleOpts(title="标题", pos_left="center") |
yaxis_opts | y轴配置项 | yaxis_opts=opts.AxisOpts(name="累计确诊人数") |
xaxis_opts | x轴配置项 | xaxis_opts=opts.AxisOpts(name="时间") |
legend_opts | 图例配置项 | legend_opts=opts.LegendOpts(pos_left='70%') |
基础地图
视觉映射器
基础柱状图
bar
from pyecharts.chars import Bar #构建柱状图对象 bar=Bar() #添加x轴数据 bar.add_xaxis(["中国","美国","英国"]) #添加y轴数据 bar.add_yaxis("GDP",[30,20,10]) #绘图 bar.render("基础柱状图.html")
反转x轴和y轴
#构建柱状图对象 bar=Bar() #添加x轴数据 bar.add_xaxis(["中国","美国","英国"]) #添加y轴数据 bar.add_yaxis("GDP",[30,20,10]) #反转xy轴 bar.reversal_axis() #绘图 bar.render("基础柱状图.html")
数值标签在右侧
#构建柱状图对象 bar=Bar() #添加x轴数据 bar.add_xaxis(["中国","美国","英国"]) #添加y轴数据 bar.add_yaxis("GDP",[30,20,10],label_opts=LabelOpts(position="right")) #反转xy轴 bar.reversal_axis() #绘图 bar.render("基础柱状图.html")
基础时间线状图
Timeline()-时间线
柱状图描述的是分类数据,回答的是每一个分类中『有多少?』这个问题. 这是柱状图的主要特点,同时柱状图很难动态的描述一个趋势性的数据. 这里pyecharts为我们提供了一种解决方案-时间线
如果说一个Bar、Line对象是一张图表的话,时间线就是创建一个一维的x轴,轴上每一个点就是一个图表对象
创建时间线
from pyecharts . charts import Bar, Timeline from pyecharts . options import * bar1 = Bar() bar1. add_ .xaxis(["中国", "美国","英国"]) bar1. add_ yaxis("GDP", [30, 20, 10], Label_ opts=Labe' LOpts(position="right" )) bar1. reversal_ axis() bar2 = Bar() bar2. add_ .xaxis(["中国", "美国","英国"]) bar2. add_ yaxis("GDP", [50, 3日, 20], label_ opts=LabelOpts (position="right")) bar2. reversal_ axis() #创建时间线对象 timeline = Timeline() # timeline对象添加bar柱状图 timeline. add(bar1, "2021年GDP") timeline . add(bar2,"2022年GDP") #通过时间线绘图 timeline . render("基础柱状图-时间线. htmL")
自动播放
#设置自动播放 timeline . add_ schema (play_ interval=1000, #自动播放的时间间隔,单位毫秒 is_ _timeline_ .show=True, #是否在自动播放的时候,显示时间线 is_ _auto_ pLay=True, #是否自动播放 is_ _Loop_ pLay=True) #是否循环自动播放
时间线设置主题
from pyecharts.globals import ThemeType #创建时间线对象 timeline=Timeline({"theme":ThemeType.LIGHT})
动态柱状图
列表的sort方法
在前面我们学习过sorted函数,可以对数据容器进行排序。
在后面的数据处理中,我们需要对列表进行排序,并指定排序规则,sorted函数就无法完成了。
我们补充学习列表的sort方法。
使用方式
列表.sort(key=选择排序依据的函数, reverse=True|False)
参数key,是要求传入一个函数,表示将列表的每一个元素都传入函数中,返回排序的依据
参数reverse,是否反转排序结果,True表示降序,False表示升序
带名函数形式
处理数据
读取数据,删除第一条数据
f=open("D:/","r",encoding="GB2312") lines=f.redlines() #读取全部数据行 lines.pop(0) #删除第一行
将数据转换为字典存储
格式为:{ 年份: [ [国家, gdp], [国家,gdp], ...... ], 年份: [ [国家, gdp], [国家,gdp], ...... ], ...... }
准备时间线
面向对象
1.在程序中设计表格,我们称之为:设计类(class)
class Student: *类名 name=None #记录学生姓名
-
在程序中打印生产表格,我们称之为:创建对象
#基于类创建对象 stu_1=Student() stu_2=Student()
-
在程序中填写表格,我们称之为:对象属性赋值
stu_1.name="ss" #为学生1赋予名称属性 stu_2.name="aa" #为学生2赋予名称属性
class是关键字,表示要定义类了
类的属性,即定义在类中的变量(成员变量)
类的行为,即定义在类中的函数(成员方法)
创建类对象的语法
对象=类名称()
成员方法
类中:不仅可以定义属性用来记录数据也可以定义函数,用来记录行为
其中:类中定义的属性(变量),我们称之为:成员变量
类中定义的行为(函数),我们称之为:成员方法
定义语法
def 方法名(self,形参1,形参2.....): 方法体
self关键字是成员方法定义的时候,必须填写的。
它用来表示类对象自身的意思
当我们使用类对象调用方法的是,self会自动被python传入在方法内部,想要访问类的成员变量,必须使用self
class Student: name=None def s(self): print("Hello") def a(self,mad): print(f"含参数,{mad}") student=Student() student.s() #不需要传参 student.a("hh") #需要传入参数
class Student: name=None def s(self): print(f"Hello,{self.name}") def a(self,mad): print(f"含参数,{mad}") student=Student() student.name="aaa" student.s() #不需要传参
尽管在参数列表中,但是传参的时候可以忽略它
类和对象
对象名=类名称()
构造方法 :init()方法
在创建类对象(构造类)的时候,会自动执行。
在创建类对象(构造类)的时候,将传入参数自动传递给init方法使用。
def _init_(self,name,age,tel): self.name=name self.age=age sel.tel=tel
变量是定义在构造方法内部,如果要成为成员变量,需要用self来表示。
其他内置方法
内置的类方法,各自有各自特殊的功能,这些内置方法我们称之为:魔术方法
str 字符串方法
class Student: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return f"Student类对象,name={self.name},age={self.age}" stu=Student("aa",22) print(stu) #如果没有str,则输出为地址 #<__main__.Student object at 0x000002775C131790> #加上后为:Student类对象,name=aa,age=22
控制类转换为字符串的行为。
方法名:str
返回值:字符串
内容:自行定义
lt 小于符号比较方法
class Student: def __init__(self,name,age): self.name=name self.age=age def __lt__(self, other): return self.age<other.age stu1=Student("aa",11) stu2=Student("bb",33) print(stu1<stu2) #True print(stu1>stu2) #False #如果没有这个函数会直接报错
直接对2个对象进行比较是不可以的,但是在类中实现lt方法,即可同时完成:小于符号 和 大于符号 2种比较
方法名:lt
传入参数:other,另一个类对象
返回值:True 或 False
内容:自行定义
比较大于符号的魔术方法是:gt不过,实现了lt,gt就没必要实现了
le 小于等于比较符号方法
可用于:<=、>=两种比较运算符上
class Student: def __init__(self,name,age): self.name=name self.age=age def __le__(self, other): return self.age<other.age stu1=Student("aa",11) stu2=Student("bb",33) print(stu1<=stu2) #True print(stu1>=stu2) #False
方法名:le
传入参数:other,另一个类对象
返回值:True 或 False
内容:自行定义
大于等于符号实现的魔术方法是:ge不过,实现了le,ge就没必要实现了
eq,比较运算符实现方法
class Student: def __init__(self,name,age): self.name=name self.age=age def __eq__(self, other): return self.age==other.age stu1=Student("aa",11) stu2=Student("bb",11) print(stu1==stu2) #True
不实现eq方法,对象之间可以比较,但是是比较内存地址,也即是:不同对象==比较一定是False结果。
实现了eq方法,就可以按照自己的想法来决定2个对象是否相等了。
面向对象3大主要特性:封装,继承,多态
封装
面向对象的简单理解是:基于模板(类)去创建实体(对象),使用对象完成功能开发。
封装表示的是将现实世界事物的:属性行为,封装到类中,描述为:成员变量,成员方法。从而完成程序对现实世界事物的描述
类中提供了私有成员的形式来支持。私有成员变量,私有成员方法。
私有成员
定义私有成员的方式非常简单,只需要:
私有成员变量:变量名以开头(2个下划线)
私有成员方法:方法名以开头(2个下划线)
即可完成私有成员的设置
私有方法无法直接被类对象使用
私有变量无法赋值,也无法获取值
私有成员无法被类对象使用,但是可以被其它的成员使用。
class Phone: __dd=2 def __a(self): print("aa") def call_aa(self): if self.__dd>=1: self.__a() print("好啦") else: print("失败") phone=Phone() print(phone.call_aa())
在类中提供仅供内部使用的属性和方法,而不对外开放(类对象无法使用)
继承
继承分为:单继承和多继承
继承表示:将从父类那里继承(复制)来成员变量和成员方法(不含私有)
语法
单继承
class 类名(父类名):
类内容体
class Phone: Producer="xoxo" IMI=None def call_4g(self): print("4G") class Phone2(Phone): color="red" def call_5G(self): print("5G") phone=Phone2() print(phone.color) print(phone.Producer) phone.call_5G() phone.call_4g()
多继承
class 类名(父类1,父类2,......父类n):
类内容体
class Phone: Producer="xoxo" IMI=None def call_4g(self): print("4G") class NFCcard: N_tpc="5" producer="aa" def read_NFC(self): print("read") def write_NFC(self): print("write") class red_line: r_type="red" def co_r(self): print("发射") class Myphone(Phone,NFCcard,red_line): pass phone2=Myphone() phone2.read_NFC() print(phone2.N_tpc)
注意事项
多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。即:先继承的保留,后继承的被覆盖
pass关键字
pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思
复写
子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。即:在子类中重新定义同名的属性或方法即可。
class Phone: Producer="xoxo" IMI=None def call_4g(self): print("4G") class Phone2(Phone): Producer="aaa" def call_4g(self): print("good") phone3=Phone2() print(phone3.Producer) phone3.call_4g()
调用父类同名成员
一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员
如果需要使用被复写的父类的成员,需要特殊的调用方式:
方式1:调用父类成员
使用成员变量:父类名.成员变量
使用成员方法:父类名.成员方法(self)
方式2:使用super()调用父类成员
使用成员变量:super().成员变量
使用成员方法:super().成员方法()
只能在子类内调用父类的同名成员。子类的类对象直接调用会调用子类复写的成员
class Phone: Producer="xoxo" IMI=None def call_4g(self): print("4G") class Phone2(Phone): Producer="aaa" def call_4g(self): Phone.call_4g(self) print(Phone.Producer) #法二:super().call_4g() #print(super().Producer) print("good") phone3=Phone2() print(phone3.Producer) phone3.call_4g()
类型注解
Python在3.5版本的时候引入了类型注解,以方便静态类型检查工具,IDE等第三方工具。
类型注解:在代码中涉及数据交互的地方,提供数据类型的注解(显式的说明)。
主要功能:帮助第三方IDE工具(如PyCharm)对代码进行类型推断,协助做代码提示
帮助开发者自身对变量进行类型注释
支持:变量的类型注解,函数(方法)形参列表和返回值的类型注解
语法:
为变量设置类型注解
语法:变量:类型
#基础数据类型注解 var_1:int=10 var_2:float=3.14 var_3:bool=True var_4:str="aa" #类对象类型注解 class Student: pass stu:Student=Student() #基础容器类型注解 my_list:list=[1,2] my_tuple:tule=(1,2,3) my_set:set={1,2} my_dict:dict={"aa":11} my_str:str="bb" #容器类型详细注解 my_list:list[int]=[1,2] my_tuple:tuple[str,int,bool]=("aa",33,True) my_set:set[int]={1,2} my_dict:dict[str,int]={"aa":11}
元组类型设置类型详细注解,需要将每一个元素都标记出来
字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value
在注释中进行类型注解
语法:
# type: 类型
var_1=random.randint(1,10) #type:int var_2=json.loads(data) #type:dict[str,int]
为变量设置注解,显示的变量定义,一般无需注解
一般,无法直接看出变量类型之时会添加变量的类型注解
类型注解仅仅是提示性的,不是决定性的
函数(方法)的类型注解
形参注解
def 函数方法名(形参名:类型,形参名:类型......): pass
函数(方法)的返回值也是可以添加类型注解的。
def 函数方法名(形参名:类型,形参名:类型......)->返回值类型: pass
Union类型
使用Union[类型, ......, 类型]可以定义联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用
多态
指的是:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。
多态常作用在继承关系上。比如
函数(方法)形参声明接收父类对象
实际传入父类的子类对象进行工作
即:
以父类做定义声明
以子类做实际工作用
以获得同一行为, 不同状态
如果父类的方法,是空实现(即用pass占位)
这种设计的含义是:
父类用来确定有哪些方法
具体的方法实现,由子类自行决定这种写法,
就叫做抽象类(也可以称之为接口)
抽象类:含有抽象方法的类称之为抽象类
抽象方法:方法体是空实现的(pass)称之为抽象方法
抽象类就好比定义一个标准,包含了一些抽象的方法,要求子类必须实现。
配合多态,完成抽象的父类设计(设计标准),具体的子类实现(实现标准)
正则表达式
正则表达式,又称规则表达式(Regular Expression),是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式(规则)的文本。简单来说,正则表达式就是使用:字符串定义规则,并通过规则去验证字符串是否匹配。比如,验证一个字符串是否是符合条件的电子邮箱地址,只需要配置好正则规则,即可匹配任意邮箱。比如通过正则规则: (^[\w-]+(.[\w-]+)*@[\w-]+(.[\w-]+)+$) 即可匹配一个字符串是否是标准邮箱格式但如果不使用正则,使用if else来对字符串做判断就非常困难了。
基础匹配
Python正则表达式,使用re模块,并基于re模块中三个基础方法来做正则匹配。
分别是:match、search、findall 三个基础方法
re.match
(匹配规则, 被匹配字符串)从被匹配字符串开头进行匹配, 匹配成功返回匹配对象(包含匹配的信息),匹配不成功返回空。
search
(匹配规则, 被匹配字符串)搜索整个字符串,找出匹配的。从前向后,找到第一个后,就停止,不会继续向后
findall
(匹配规则, 被匹配字符串)匹配整个字符串,找出全部匹配项
元字符匹配
单字符匹配
示例:字符串 s = “itheima1 @@python2 !!666 ##itcast3”
找出全部数字: re.findall(r‘\d’, s) 加上r表示转义字符无效,就是普通字符
字符串的r标记,表示当前字符串是原始字符串,即内部的转义字符无效而是普通字符
找出特殊字符:re.findall(r‘\W’, s)
找出全部英文字母:re.findall(r’[a-zA-Z]’, s)
[]内可以写:[a-zA-Z0-9] 这三种范围组合或指定单个字符如[aceDFG135]
数量匹配
比如\d*或者其他