python基础(中)
2020-11-15 20:23:17 0 举报
AI智能生成
登录查看完整内容
python语法基础 中
作者其他创作
大纲/内容
python基础(中)
正则
定义和作用
是什么
它是约束字符串匹配某种形式的规则
有什么用
检测字符串是否合规
提取网页字符串中想要的数据
爬虫正则抓信息
怎么实现
python re模块 通过NFA自动机实现
DFA自动机必须掌握
https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/5dkal2/
包含的元素种类
普通字符
元字符
用法
匹配单个字符
.
\\d
匹配数字
\\D
匹配非数字
\\w
匹配字母或数字或下划线 (支持中文)
\\W
匹配非字母或数字下划线
\\s
匹配任意的空白符( " " \ \\t \)
\\S
匹配任意非空白符
\
匹配一个换行符
\\t
匹配一个制表符
[]字符组
字符组格式
[...]
匹配字符组中的字符
[^...]
匹配除了字符组内内容之外的所有字符
字符组内容
[123abc]
匹配出字符组当中列举的字符
[0-9]
|[a-z]
匹配所有的小写字母
[A-Z]
就表示所有的大写字母
[0-9a-fA-F]
[\\w@#%_]
预定义字符集也能放字符组中
匹配多个字符
量词
?
重复0次或1次
+
重复1次或多次 (至少1次)
*
重复0次或多次 (任意次)
{n}
重复n次
重复n次或更多次 (至少n次)
重复n到m次
贪婪与非贪婪
贪婪匹配: 默认向更多次匹配
非贪婪匹配: 默认向更少次匹配
写法: 量词加?
匹配开头结尾
边界符(了解)
卡住左边界
"word" \\bw
卡住右边界
"word" d\\b
^ $的使用
匹配分组
a|b
匹配字符a 或 字符b
"abcd|abc"
(ab)
匹配括号内的表达式
将()作为一个分组
findall
(正则表达式) 优先显示分组中的内容
(?:正则表达式) 取消优先显示分组的功能
search
\um
反向引用
引用分组num匹配到的字符串
(?P<组名>正则表达式)
命名分组
给这个组起一个名字
(?P=组名)
引用命名组
正则表达式修饰符
多个修饰符可以通过 | 拼接
常用修饰符
re.I
忽略大小写
re.M
re.S
使 . 匹配包括换行在内的所有字符
相关函数
通过正则匹配出第一个对象返回
obj.group() 获取匹配的内容
obj.groups() 获取分组当中的内容(返回元组)
match
等价于search在正则表达式的前面加上^
compile
pattern = re.compile("\\d+"); obj = pattern.search(strvar)
split
sub
subn
finditer
常用正则
匹配小数
\\d+\\.\\d+
匹配小数和整数
\\d+(?:\\.\\d+)?
匹配中文
[\\u4e00-\\u9fa5]+
匹配双字节字符
[^\\x00-\\xff]+
不以xx开头
(?!_)
不以xx结尾
(?!.*?_$)
^(?!_)(?!.*?_$)[0-9_\\u4e00-\\u9fa5]+$
小程序: 计算器
递归实现
死循环实现
模块导入
模块和包
import
导入模块
import 模块 as 后面写这个模块的别名
导入任意路径下任意模块
import按绝对路径导入
手动追加 sys.path.append(r"D:\\32期\\d18")
导入包及其中模块
from .. import ..
导入具体成员
from .. import .. as ..
导入所有成员
from .. import *
导入包中模块下成员
from package1.module2 import ..
__name__的使用
单入口模式
主入口仍通过绝对路径进行导入
分模块可以使用相对路径导入
.可以无数多个
面对对象
类和对象
概念
用特征表达一类事物称为一个类
类的定义
新式类
多重继承的属性搜索顺序采用广度优先搜索
经典类
Python2里没有继承object的是经典类
多重继承的属性搜索顺序采用深度优先搜索
类的实例化
类名()
实例化时还可以赋值 obj = Car()
类的基本结构
成员属性(类变量 实例变量)
成员方法
注意: 判断和循环都应该用方法包起来
类的命名
推荐使用大驼峰命名法
封装
公有成员
在类内或者类外都可以访问
私有成员: __成员
对象的操作
对象访问类成员
对象添加公有属性
obj.新属性 = xx
类/对象.__dict__ 返回包含所有成员的字典
对象添加公有方法
无参方法
obj.func = funcobj.func()
有参方法
obj.func = funcobj.func(arg)
lambda表达式
obj.func = lambda : print("我是威震天")obj.func() # "我是威震天"
类的操作
类访问类成员
私有成员还是无法在类外访问
类添加公有属性
cls.新属性 = xx
类添加公有方法
对象和类的不同
需要熟知的两点
在类外访问私有成员
根据改名策略
_类名__成员名
通过公有方法间接访问
使用类或对象删除成员
del obj/cls.成员
继承
在python3中所有类都继承object这个父类
单继承
子类可以调用父类的公有成员
不能调用父类的私有成员
可以重写父类的公有方法
多继承
基本语法
成员调用
用类调用成员
用对象调用成员
搜索顺序: 对象本身 => 类 => 父类
用super()调用成员
菱形继承(钻石继承)
super深层理解
mro(method resolusion order): 方法解析顺序
super作用: 专门用于解决复杂的多继承调用顺序关系
super的调用顺序: 会按照c3算法的广度优先原则进行调用
判断子父关系
issubclass
判断类的子父关系(应用在类与类之间)
isinstance
判断对象类型(应用在对象与类之间)
注意: 只要在一条继承链上满足关系即可
多态
涉及
应用场景
注意
示例: 根据不同需求执行不同子类
单态
原因
场景
示例: 使用__new__只实例化一个对象
类中的方法
普通无参方法
绑定方法: (1) 绑定到对象 (2) 绑定到类
实例方法
类方法
@classmethod装饰
无论对象还是类都可以调用
静态方法
@staticmethod装饰
方法变属性
property()
可以把方法变成属性
@property
是一个类装饰器
@方法名.setter 设置属性
@方法名.deleter 删除属性
反射
通过字符串操作类对象或者模块中相关成员的操作
反射类/对象的成员
hasattr() 检测对象/类是否有指定的成员
返回True或False
getattr() 获取对象/类成员的值
setattr() 设置对象/类成员的值
delattr() 删除对象/类成员的值
模块的反射
__new__
触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
功能:控制对象的创建过程
返回值:通常返回对象或None
注意点
返回None或其他对象时后面__init__不再触发
__init__ (构造方法)
功能:为对象添加成员
返回值:无
__del__ (析构方法)
触发时机: 当对象被内存回收的时候自动触发
页面执行完毕回收所有变量
所有对象被del的时候
功能:对象使用完毕后资源回收
参数:一个self接受对象
程序: 模拟读取文件
__call__
触发时机:把对象当作函数调用的时候自动触发
功能: 模拟函数化操作
返回值: 看需求
程序: 模拟int强转
强转操作
__str__
触发时机: 使用print(对象)或者str(对象)的时候触发
功能: 查看对象
参数: 一个self接受当前对象
返回值: 必须返回字符串类型
__repr__
触发时机: 使用repr(对象)的时候触发
__bool__
触发时机:使用bool(对象)的时候自动触发
功能:强转对象
参数:一个self接受当前对象
返回值:必须是布尔类型
计算操作
__add__
触发时机:使用对象进行运算相加的时候自动触发
功能:对象运算
参数:二个对象参数
返回值:运算后的值
元素操作
__len__
触发时机:使用len(对象)的时候自动触发
功能:用于检测对象中或者类中某个内容的个数
返回值:必须返回整型
程序: 获取自定义成员数
魔术属性
__dict__
不包括父类成员
__doc__
__name__
__class__
__bases__
程序错误
语法错误
代码没有按python规定写
SyntaxError: ...
异常错误
常见异常
IndexError
索引超出序列的范围
KeyError
字典中查找一个不存在的关键字
NameError
尝试访问一个不存在的变量
IndentationError
缩进错误
AttributeError
尝试访问未知的对象属性
StopIteration
迭代器没有更多的值
AssertionError
断言语句(assert)失败
其他常见错误
异常处理
基础语法
try .. except .. 抑制报错
功能
扩展
BaseException是所有异常类的父类
Exception是常规异常类的父类
带有分支的异常处理
多个except分支
同一个except分支多个异常类型
捕获错误并输出报错内容
except StopIteration as e:\tprint(e)
其他写法
try .. except .. else ..
try .. finally ..
try .. except .. else .. finally ..
主动抛异常
程序: 模拟系统抛出异常
函数
基本概念
包裹一部分代码,实现某一个功能
特点
可以反复调用,提高代码的复用性,提高开发效率,便于维护管理
格式
def 函数名(): code1 code2函数名()
命名
命名规则同变量
驼峰命名法
1) 大驼峰命名法:每个单词首字母大写(类的命名)
mycar => MyCar
2) 小驼峰命名法:首个单词首字母小写,其他单词首字母大写
mycar => myCar
_命名法
可以将不同的单词用_拼接在一起
symmetric_difference()
函数的参数
参数:函数运算时需要的值
参数种类
形参
形式参数,在函数的定义处
实参
实际参数,在函数的调用处
常见用法
位置参数
即普通形参和普通实参,位置顺序逐一对应
默认形参
如果有实参,那么使用实参。
如果没有实参,那么用形参的默认值
普通形参 + 默认形参
普通形参必须放在默认形参前,否则报错
关键字实参
如果都是关键字实参,可以任意调整实参的顺序
普通实参必须写在关键字实参的前面
收集形参
普通收集形参
专门收集多余的普通实参,并打包为元组
func(*args)
关键字收集形参
专门收集多余的关键字实参,并打包为字典
func(**kwargs)
收集所有参数
命名关键字参数
在调用函数时,必须使用关键字实参的形式来进行调用
星号的使用
*和**,在函数的定义处,负责打包(把实参都收集过来,放在元组或字典中)
形参声明的位置顺序
普通参数 -> 默认参数 -> 收集参数 -> 命名关键字参数 -> 关键字收集参数
return
把函数内部的数据返回到函数的调用处
return + 六大标准数据类型,此外,还可以返回 函数 或 类对象
return 在执行时意味终止函数,后面代码不再执行
如果不定义return返回值,默认返回None
全局变量和局部变量
全局变量
在函数外部定义的变量或者在函数内部使用global关键字声明
局部变量
在函数内部定义的变量
作用域
全局变量的作用范围横跨整个文件,函数内能引用但不能直接修改
局部变量的作用范围仅仅在函数的内部,函数外不能引用
生命周期
该变量的作用时长
全局命名空间:func,全局变量...
局部命名空间:局部变量
内置命名空间->全局命名空间->局部命名空间 (开辟空间顺序)
内置属性 > 全局属性 > 局部属性(生命周期:从长到短)
global的使用
若当前不存在全局变量,可以在函数内部通过global关键字定义
若当前存在全局变量,想要在函数内部修改并全局生效,先global一下
函数名的使用
动态创建
动态销毁
当参数传递
作为值返回
作为容器型数据的元素
__doc__或者help查看文档
在函数名之下可以写多行注释说明,能用help()和__doc__查看
函数的嵌套
互相嵌套,外层的为外函数,内层为内函数
LEGB原则
找寻变量的调用顺序采用LEGB原则(就近原则)
nonlocal的使用
用来修改局部变量
nonlocal一个变量,遵循LEGB原则
nonlocal只能修改局部变量
容器型的局部变量可以不通过nonlocal修改,因为传的是地址
闭包
互相嵌套的两个函数,1.如果内函数使用了外函数的局部变量,2.并且外函数把内函数返回出来,这个过程叫做闭包,里面的内函数叫做闭包函数
闭包特点
内函数引用了外函数的局部变量,会延长该变量生命周期
闭包意义
可以优先使用外函数中的变量,对闭包中的值起到了封装保护的作用,外部无法访问
示例: 求最后结果
匿名函数lambda
用一句话来表达只有返回值的函数
语法
lambda 参数:返回值
简洁,高效
无参的lambda
lambda: "abc"
有参的lambda
lambda n: n * 3
三元运算符
只用于双向分支
真值 if 条件表达式 else 假值
条件表达式True,返回if前面的值,反之,返回else后面的值
有判断条件的lambda
locals与globals
locals
获取当前作用域所有的变量
locals 在函数外,获取的是打印之前所有的全局变量
locals 在函数内,获取的是调用之前所有的局部变量
globals
只获取全局空间的全局变量
globals 在函数外,获取的是打印之前所有的全局变量
globals 在函数内,获取的是调用之前所有的全局变量
功能:批量创建全局变量
globals,以字典格式返回全局变量,在该字典中增加数据,就是增加新的全局变量
迭代器
能被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator 迭代器是对象)
迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果而继续的,单纯的重复并不是迭代
特征
不依赖索引,而通过next指针(通过内存地址找数据)迭代所有数据,一次只取一个值,而不是一次把所有数据放进内存,大大节省空间。
可迭代对象与迭代器
可迭代对象 -> 迭代器 = 从不能被next直接调用 -> 可以直接被next指针调用
可迭代对象不一定是迭代器,迭代器一定是可迭代对象
创建
iter()一个可迭代对象
判断
1.判断是否有__iter__和__next__,dir()可以返回入参的属性、方法列表
2.isinstance()判断是否为迭代器/可迭代对象
调用
next()
指针next是单向不可逆的过程,一直走到头
for循环
一次性把内容处理完,大数据时不可用
for + next
可以选择范围,数据量很大时,推荐使用,注意超出能迭代的范围会报错
强转为其他容器
转为其他可迭代数据过程中,也会进行完整迭代数据量很小时,可以使用
重置
重iter()一下
高阶函数
能够把函数当成参数传递的就是高阶函数
map
处理数据
把iterable的数据一个一个传给前面的func处理
参数
func:函数(内置函数,自定义函数)
iterable:可迭代对象(容器型数据,range对象,迭代器)
返回值
示例一:列表中的纯数字字符串变为整型
示例二:列表的数分别左移得到另一组数
示例三:处理列表得到有映射关系的另一组数据
reduce
计算数据
把前两个数据用func运算后,把结果与第三个元素运算,重复
func:自定义函数
计算的结果
示例一:多个数字组合为一个数
示例二:纯数字字符串不用int变为纯数字
filter
过滤数据
返回执行结果为True的入参
示例:过滤奇数保留偶数
sorted
排序数据
key :指定函数(自定义/内置)
reverse :是否倒序
列表
示例一:按绝对值从小到大进行排序
示例二:按自定义函数进行排序
与sort的区别
可以排序所有的容器类型数据,sort只能处理列表
返回一个新的列表,sort会改变原列表
推导式
通过一行循环判断遍历出一系列数据
val for val in iterable
列表推导式
推导式基本语法
带有判断条件的推导式
lst_new = [i for i in lst if i % 2 == 1]
多循环推导式
lst_new = [i + "_" + j for i in lst1 for j in lst2]
带有判断条件的多循环推导式
lst_new = [i + "_" + j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j)]
推导式练习
集合推导式
跟列表推导式相似,唯一区别使用的是大括号
示例:开卡系统
字典推导式
{key_expr:value_expr for value in collection if condition}
enumerate
枚举,将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
start:可以选择开始的索引号(默认从0开始索引)
示例:把列表转为字典
zip
按照索引配对
将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
示例一:把多个容器组合为字典
示例二: 可滑动序列
生成器
就是允许自定义逻辑的迭代器
迭代器和生成器区别
迭代器本身是系统内置的,重写不了,而生成器是用户自定义的,可以重写迭代逻辑
创建方式
生成器表达式
里面是推导式,外面用圆括号
gen = (i for i in range(100))
生成器函数
yield
类似return,不过每次在返回值后会记住该位置,再调用时从此处往下走
优化生成器代码
一般用for + next,选择一个范围调用,防止处理大数据耗时太久
send的使用
不仅调用,还给上一个yield发值,覆盖其在生成器中后续再使用的值
send,对比next,不但能取值,还能发送值
第一个 send 不能给 yield 传值 默认只能写None
最后一个yield 接受不到send的发送值
示例:一个能被调用三次的生成器
yield from的使用
将一个可迭代对象变成一个迭代器返回
斐波那契数列
使用生成器分段获取所有内容,而不一次把所有数据全部打印
递归函数
线性递归
栈帧空间
总结
递归就是不断开辟与释放栈帧空间的过程
递归触发归的两种情况
最后一层栈帧空间执行结束
遇到return终止当前函数
所以一定要给出跳出的条件
开辟的栈帧空间数据彼此独立不共享
经典示例一: 阶乘
经典示例二: 斐波那契数列
经典示例三: 青蛙跳台阶
尾递归
写法
经典示例一: 尾递归实现阶乘
优化一: 设默认值
优化二: 设默认值 + 隐藏该值
经典示例二: 尾递归实现斐波那契数列
内存栈区堆区(了解)
装饰器
函数装饰器
装饰器原型
@符号
装饰器的标识符
自动把下面修饰的原函数当成参数传递给装饰器
把返回的新函数去替换原函数
装饰器嵌套
装饰器的执行顺序是从下到上依次进行功能的扩展
带有参数的装饰器
原函数和新函数参数和返回值要保持一一对应
带有参数返回值的装饰器
返回值: 最后的返回值是wrapper的返回值
放在类中的装饰器
带有参数的函数装饰器
作用于类的装饰器
类装饰器
标准库
内置函数
abs()
绝对值函数
abs(-1)
round()
四舍五入
n.5的情况,奇进偶不进
res = round(2.5) # 2
res = round(3.5) # 4
sum()
求和
res = sum(lst)
max()/min()
求最大值/最小值
max(tup)
pow()
求乘方
若三个参数,前两个乘方与第三个数取余
range()
产生指定范围的可迭代对象
bin()
转为二进制
bin(8)
otc()
转为八进制
oct(8)
hex()
转为十六进制
hex(16)
chr()
ASCII编码转为字符
大写字母65~90,小写字母97~122
chr(65)
ord()
字符转为ASCII编码
ord("A")
eval()
将字符串当作python代码执行
局限性:不能创建变量
exec()
功能更强大
repr()
不转义字符输出字符串
input()
接收输入字符串
hash()
生成hash值
可用与加密和文件校验
数学模块 math
ceil()
向上取整 (对比内置round)
math.ceil(-3.45)
floor()
向下取整 (对比内置round)
math.floor(3.99)
乘方 (结果为浮点数) (对比内置pow)
必须是两个参数
sqrt()
开平方 (结果浮点数)
math.sqrt(9)
fabs()
绝对值 (结果浮点数) (对比内置abs)
math.fabs(-1)
modf()
将一个数拆成整数和小数组成元组
math.modf(3.897)
copysign()
复制参数2的符号给参数1 (返回一个小数)
fsum()
求和 (结果浮点数)(对比内置sum)
math.fsum(lst)
pi
圆周率常数
math.pi
随机模块 random
random()
获取随机0-1之间的小数(左闭右开)
random.random()
randrange()
randint()
获取指定范围的随机整数 (了解)
uniform()
获取指定范围的随机小数 (左闭右开)
choice()
随机获取序列中的值(多选一)
sample()
随机获取序列中的值(多选多) [返回列表]
random.sample(lst)
shuffle()
随机打乱可修改序列中的值(直接打乱原序列)
random.shuffle(lst)
示例:验证码
序列化模块
序列化
把不能直接存储在文件中的数据变得可存储
反序列化
把存储在文件中的数据拿出来恢复成原来的数据
pickle
主要用于存储数据,把数据序列化成二进制字节流
dumps()
把任意对象序列化成一个bytes
loads()
把任意bytes反序列化成原来数据
dump()
把对象序列化后写入到file-like Object(即文件对象)
load()
把file-like Object中的内容拿出来,反序列化成原来数据
json
主要应用于传输数据,序列化成字符串
json字符串
所有编程语言都能识别,本身是字符串
条件
可被json序列化:int float bool str list tuple dict None
dumps 和 loads
ensure_ascii=False 显示中文
sort_keys=True 按键排序
dump 和 load
pickle和json的区别
pickle能序列化所有数据为bytes,限python内部存储传输
json能序列化大部分类型数据为str,所有编程语言都识别
(int float bool)(str list tuple dict None)(很多语言没有set)
能否连续load
pickle可以连续load,多套数据放到同一个文件中
json不能连续load,只能一次性拿出所有数据
时间模块 time
相关知识
时间戳
从1970年1月1日0时0分0秒到指定时间之间的秒数
时间元组
前六位,年月日时分秒
格式化时间字符串
%Y-%m-%d %H:%M:%S
time()
获取本地时间戳
time.time()
localtime()
时间戳 =>时间元组(参数是时间戳,默认当前)
time.localtime(1601368838)
mktime()
时间元组 =>时间戳(参数是时间元组)
time.mktime(ttp)
ctime()
时间戳 =>时间字符串(参数是时间戳,默认当前)
time.ctime(1601368838)
strftime()
strptime()
sleep()
程序睡眠等待
time.sleep(5)
asctime()
时间元组 =>时间字符串(参数是时间元组)
不推荐使用
perf_counter()
计时
示例:进度条
系统模块 os
system()
在python中执行系统命令
os.system("ifconfig")
popen()
执行系统命令返回对象,能通过read方法读出字符串
listdir()
获取文件夹中所有内容的名称列表
os.listdir()
getcwd()
获取当前.py的绝对路径,不带文件名
os.getcwd()
chdir()
修改当前文件工作的默认路径
os.chdir("/mnt/hgfs/python")
enviro()
获取或修改环境变量,返回字典
os.environ["path"] += ":/home/chenlu"
属性
name
os.name,获取系统标识
linux/mac -> posix ,windows -> nt
sep
os.sep,获取路径分割符号
linux/mac -> /,window-> \\
linesep
os.linesep,获取系统的换行符号
linux/mac -> \,window->\\ 或 \
路径模块 os.path
basename()
返回文件名部分
os.path.basename(pathvar)
dirname()
返回路径部分
os.path.dirname(__file__)
split()
将路径拆成文件和路径部分,组成一个元组
os.path.split(__file__)
join()
将多个路径拼成新的路径,自动加不同系统的斜杠
splitext()
将路径分割为后缀和其他部分(了解)
getsize()
获取文件的大小
os.path.getsize(path_new)
isdir()
检测路径是否是一个文件夹
os.path.isdir(pathvar)
isfile()
检测路径是否是一个文件
islink()
检测路径是否是一个链接
getctime()
获取文件create time(时间戳)
[windows]文件的创建时间
[linux]权限的改动时间
getmtime()
获取文件最后一次modify时间(时间戳)
getatime()
获取文件最后一次access时间(时间戳)
exists()
检测指定的路径是否存在
isabs()
检测一个路径是否是绝对路径
abspath()
相对路径 =>绝对路径
示例:计算文件夹大小
文件操作模块
os 新建/删除
mknod()
创建文件,os.mknod("test1.txt")
remove()
删除文件
mkdir()
创建目录(文件夹)
rmdir()
删除目录(空文件夹)
rename()
makedirs()
递归创建文件夹,os.makedirs("a/b/c/d")
removedirs()
递归删除文件夹(空文件夹),os.removedirs("a/b/c/d")
shutil 复制/移动
copyfileobj()
复制文件对象
copyfile()
仅复制文件内容,底层调用了copyfileobj
copymode()
复制文件权限,不包括内容
要先有文件
copystat()
复制所有状态信息,不包括内容
copy()
复制文件权限和内容
copy2()
复制文件权限、内容和状态信息
copytree()
拷贝文件夹里所有内容(递归拷贝)
rmtree()
删除当前文件夹及其中所有内容(递归删除)
move()
移动文件或者文件夹,可以重命名
压缩模块
zipfile
zipfile.ZipFile()
默认只打包,要压缩则传参zipfile.ZIP_DEFLATED
压缩文件
用ZipFile以w模式打开压缩包对象,用write添加内容,用close关闭
解压文件
r模式打开
zf.extractall(路径)
追加文件
a模式打开
查看压缩包内容
zf.namelist()
tarfile
打包模式
w 单纯的套tar后缀,打包
w:bz2 采用bz2算法压缩
理论上压缩后最小
w:gz 采用gz算法压缩
相关操作
用open以w模式打开压缩包对象,用add添加内容,用close关闭
同zipfile
只能对没有压缩过的tar包添加
tf.getnames()
改进tarfile添加功能
1.把已经压缩的包进行解压
2.把要追加的内容放进去
3.过滤文件重新压缩
0 条评论
回复 删除
下一页