python基础(中)
2020-11-15 20:23:17 0 举报
AI智能生成
python语法基础 中
作者其他创作
大纲/内容
正则
定义和作用
是什么
它是约束字符串匹配某种形式的规则
有什么用
检测字符串是否合规
手机号, 身份证号...
提取网页字符串中想要的数据
爬虫正则抓信息
怎么实现
python re模块 通过NFA自动机实现
涉及回溯, 所以正则必须注意写好
DFA自动机必须掌握
https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/5dkal2/
包含的元素种类
普通字符
大小写字母, 数字
元字符
预定义字符集, 量词, 边界符, 分组
用法
tip: 为了防止转义, 在正则表达式或要匹配的字符串前, 加r实现匹配
匹配单个字符
.
匹配除了换行符\n的任意字符, 常作为.*?使用
\d
匹配数字
\D
匹配非数字
\w
匹配字母或数字或下划线 (支持中文)
\W
匹配非字母或数字下划线
\s
匹配任意的空白符( " " \r \t \n)
\S
匹配任意非空白符
\n
匹配一个换行符
\t
匹配一个制表符
[]字符组
字符组格式
[...]
匹配字符组中的字符
[^...]
匹配除了字符组内内容之外的所有字符
字符组内容
[123abc]
匹配出字符组当中列举的字符
[0-9]
可用 - 表示范围, [0-9] 和 [0123456789]是一个意思
|[a-z]
匹配所有的小写字母
[A-Z]
就表示所有的大写字母
[0-9a-fA-F]
可以匹配数字, 大小写形式的a-f, 该正则可验证十六进制
[\w@#%_]
预定义字符集也能放字符组中
tip: 匹配 ^ - \ . ( [等符号时, 需要前面加\转义
匹配多个字符
量词
?
重复0次或1次
+
重复1次或多次 (至少1次)
*
重复0次或多次 (任意次)
{n}
重复n次
{n,}
重复n次或更多次 (至少n次)
{n,m}
重复n到m次
贪婪与非贪婪
贪婪匹配: 默认向更多次匹配
回溯算法: 从左向右进行匹配, 直到遇到不匹配的, 返回到上一个匹配位置
非贪婪匹配: 默认向更少次匹配
写法: 量词加?
匹配开头结尾
边界符(了解)
卡住左边界
"word" \bw
卡住右边界
"word" d\b
^ $的使用
^ 是在字符串的开头, 表达必须以某个字符开头
$ 是在字符串的结尾, 表达必须以某个字符结尾
tip: 当使用了^ $, 代表要把该字符串看成一个整体
匹配分组
a|b
匹配字符a 或 字符b
若两个当中有重合部分, 把更长的那个放前面
"abcd|abc"
(ab)
匹配括号内的表达式
将()作为一个分组
findall
(正则表达式) 优先显示分组中的内容
(?:正则表达式) 取消优先显示分组的功能
search
从左到右, 匹配到一组内容就直接返回, 返回的是对象
\num
反向引用
引用分组num匹配到的字符串
(?P<组名>正则表达式)
命名分组
给这个组起一个名字
(?P=组名)
引用命名组
引用之前组的名字, 把该组名匹配到的内容放到当前位置
正则表达式修饰符
用法
正则函数如compile, 有个参数flags可以传修饰符
多个修饰符可以通过 | 拼接
常用修饰符
re.I
忽略大小写
re.M
多行匹配, 使每一行都单独匹配,影响 ^ 和 $
re.S
使 . 匹配包括换行在内的所有字符
相关函数
findall
匹配字符串中相应内容, 返回列表
用法: findall("正则表达式","要匹配的字符串")
search
通过正则匹配出第一个对象返回
obj.group() 获取匹配的内容
obj.groups() 获取分组当中的内容(返回元组)
match
验证用户输入内容, 了解即可
等价于search在正则表达式的前面加上^
compile
指定一个统一的匹配规则, 常用
pattern = re.compile("\d+"); obj = pattern.search(strvar)
split
切割, 比字符串切割高级, 可以按多个字符切割, 常用
sub
替换, 比replace高级, 可以替换多个字符, 常用
subn
替换, 用法同sub, 返回值不同, 多一个替换次数
finditer
匹配字符串中相应内容, 返回迭代器
常用正则
匹配小数
\d+\.\d+
匹配小数和整数
\d+(?:\.\d+)?
匹配中文
[\u4e00-\u9fa5]+
匹配双字节字符
[^\x00-\xff]+
不以xx开头
(?!_)
不以xx结尾
(?!.*?_$)
只含有汉字、数字、下划线, 不能以下划线开头和结尾
^(?!_)(?!.*?_$)[0-9_\u4e00-\u9fa5]+$
小程序: 计算器
递归实现
死循环实现
模块导入
模块和包
文件就是一个模块, 文件夹就是一个包
文件夹里面可以有很多文件, 相当于包中有许多模块
模块导入时, 不会重复, 只会导一次
import
导入模块
import 模块或者包(包是文件夹,模块是文件)
import 模块 as 后面写这个模块的别名
导入任意路径下任意模块
import按绝对路径导入
默认导入当前脚本文件同级目录下的模块, 然后会从sys.path提供的路径下去找, 找不到就报错
手动追加 sys.path.append(r"D:\32期\d18")
导入包及其中模块
导入包时, 会自动指定包中初始化文件\__init__.py, 对包进行初始化
把要引入的模块放到初始化文件中引入, 可以简化操作
Python 3.3之后, 可以导入不包含\__init__.py的目录
from .. import ..
导入具体成员
from .. import .. as ..
导入所有成员
from .. import *
在模块中设置*号, 可以指定导入的范围
导入包中模块下成员
from package1.module2 import ..
__name__的使用
当前文件直接运行, 则返回"\__main__"
当前文件间接导入, 则返回当前文件名(模块名)
__name__配合__main__使用, 把不需要导入的代码写if判断下面
单入口模式
只通过主文件来调用分模块内容, 分模块不单独执行
主入口仍通过绝对路径进行导入
分模块可以使用相对路径导入
. 代表当前路径, .. 代表上一级路径
.可以无数多个
含有相对路径的分模块不能直接执行, 需通过主入口文件间接执行
面对对象
类和对象
概念
用特征表达一类事物称为一个类
对象是类的实例, 类是对象的模板
类的定义
新式类
python3中都是新式类, 默认继承父类object
多重继承的属性搜索顺序采用广度优先搜索
经典类
Python2里没有继承object的是经典类
多重继承的属性搜索顺序采用深度优先搜索
类的实例化
类名()
实例化时还可以赋值 obj = Car()
类的基本结构
成员属性(类变量 实例变量)
成员方法
注意: 判断和循环都应该用方法包起来
类的命名
推荐使用大驼峰命名法
封装
概念
公有成员
在类内或者类外都可以访问
私有成员: __成员
在类内可以互相访问, 在类外不能访问
对象的操作
对象访问类成员
私有成员无法在类外访问, 类内可以
对象添加公有属性
obj.新属性 = xx
类/对象.__dict__ 返回包含所有成员的字典
对象添加公有方法
无参方法
obj.func = func
obj.func()
有参方法
基本, 只添加新方法
obj.func = func
obj.func(arg)
升级, 为了在新方法中使用obj的属性或方法, 将obj传参进去
obj.func = func
obj.func(obj, arg)
终极, 用types.MethodType()绑定新方法和obj, 后面就可以简写
obj.func = types.MethodType(func, obj) => 绑定方法
obj.func(arg)
lambda表达式
obj.func = lambda : print("我是威震天")
obj.func() # "我是威震天"
类的操作
类访问类成员
私有成员还是无法在类外访问
类添加公有属性
cls.新属性 = xx
类添加公有方法
用法同对象: 无参, 有参, lambda
对象和类的不同
类中的无参方法只能用类调用, 对象无法调用
对象可以调用类中的成员, 反过来, 类不能调用对象的成员
每创建一个对象, 都会在内存中占一个堆空间, 彼此之间数据独立
需要熟知的两点
在类外访问私有成员
根据改名策略
_类名__成员名
通过公有方法间接访问
修改类中的公有方法, 间接访问私有成员, 推荐
使用类或对象删除成员
del obj/cls.成员
对象能访问公有成员, 但无权修改或删除
对象在访问成员时, 优先访问该对象的自己成员, 没有才到类中寻找, 即按广度优先搜索
注意: 对象无法调用无参方法, 类可以调用对象的绑定方法
继承
概念
一个类除了自身成员, 还获取了另外一个类的成员
被继承的类叫做父类(基类, 超类), 继承的类叫做子类(衍生类)
在python3中所有类都继承object这个父类
单继承
子类可以调用父类的公有成员
不能调用父类的私有成员
可以重写父类的公有方法
多继承
基本语法
成员调用
用类调用成员
用对象调用成员
搜索顺序: 对象本身 => 类 => 父类
用super()调用成员
只调用父类的成员, 顺带传递对象参数给调用的方法
菱形继承(钻石继承)
super深层理解
super 会自动根据mro列表返回出来的顺序关系, 依次调用
mro(method resolusion order): 方法解析顺序
super作用: 专门用于解决复杂的多继承调用顺序关系
super的调用顺序: 会按照c3算法的广度优先原则进行调用
super传参: 会默认在调用方法时, 传递该对象参数
判断子父关系
issubclass
判断类的子父关系(应用在类与类之间)
isinstance
判断对象类型(应用在对象与类之间)
注意: 只要在一条继承链上满足关系即可
多态
概念
不同的子类对象, 调用相同的父类方法, 得到不同的执行结果
涉及
继承, 重写
应用场景
某个产品模块有多种功能, 开发组长把统一的方法规划和命名写在父类中, 组员用多态分别写自己负责的功能, 最后给组长调用
注意
写多继承时, 尽量避免造成不同类相同方法名的情况, 提高代码质量, 高内聚, 低耦合
高内聚: 一个模块只完成一个任务, 专一性高
低耦合: 模块与模块之间可以彼此独立不冲突, 方便移植复用
示例: 根据不同需求执行不同子类
单态
概念
同一个类, 无论实例化多少次, 都有且只有一个对象
原因
每创建一个对象, 就会在内存中多占一个堆空间, 为了节省空间, 使用单态模式
场景
只是单纯调用类中成员, 而不会额外为当前对象添加成员
示例: 使用__new__只实例化一个对象
类中的方法
普通无参方法
实际上就是没有加@staticmethod 的静态方法, 只能类自身调用
绑定方法: (1) 绑定到对象 (2) 绑定到类
实例方法
默认传调用此方法的对象, 所以要有形参self
类方法
@classmethod装饰
无论对象还是类都可以调用
默认传类, 所以要有形参cls
静态方法
@staticmethod装饰
无论是对象还是类调用静态方法, 都不会默认传递任何参数
方法变属性
property()
可以把方法变成属性
可以动态的控制属性的获取, 设置, 删除相关操作
@property
是一个类装饰器
装饰类中的方法, 把它变成属性, 值就是return的结果, 还可以修改删除这个属性
@方法名.setter 设置属性
@方法名.deleter 删除属性
反射
概念
通过字符串操作类对象或者模块中相关成员的操作
反射类/对象的成员
hasattr() 检测对象/类是否有指定的成员
返回True或False
hasattr(obj, "eye")
getattr() 获取对象/类成员的值
如果获取的值不存在, 可设置第三个参数, 防止报错
getattr(obj, "weight22", "抱歉这个值不存在")
通过类进行反射(反射出来的是普通方法, 需要给self传值)
func = getattr(C, "drink")
func(1)
通过对象进行反射(反射出来的是绑定方法, 自动传obj给self)
func = getattr(obj, "drink")
func()
setattr() 设置对象/类成员的值
setattr(obj, "skin", "white")
delattr() 删除对象/类成员的值
delattr(obj, "skin")
模块的反射
sys.modules 获取一个系统字典, key是加载的所有模块, 对应value为该模块所有成员
概念
所有以双下划线__包起来的方法, 都称为魔术方法, 会在特定时机自动触发
__new__
触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
功能:控制对象的创建过程
参数:至少一个cls接受当前的类, 其他根据情况决定, 要与__init__ 对应一致
返回值:通常返回对象或None
注意点
返回None或其他对象时后面__init__不再触发
本身不会用到接收的参数, 可以用收集参数全收集
__init__ (构造方法)
触发时机:实例化对象, 初始化的时候触发
功能:为对象添加成员
参数:参数不固定, 至少一个self参数
返回值:无
注意点: 没有此方法的话对象就没有成员, 只能访问类的成员
__del__ (析构方法)
触发时机: 当对象被内存回收的时候自动触发
页面执行完毕回收所有变量
所有对象被del的时候
功能:对象使用完毕后资源回收
参数:一个self接受对象
返回值:无
注意点: python的内存管理中有引用计数机制, 当一个对象的引用计数归0, 就会触发他的__del__
程序: 模拟读取文件
__call__
触发时机:把对象当作函数调用的时候自动触发
功能: 模拟函数化操作
参数: 参数不固定, 至少一个self参数
返回值: 看需求
程序: 模拟int强转
普通变量的基本操作, 如果应用在对象上, 也有相应的魔术方法
强转操作
__str__
触发时机: 使用print(对象)或者str(对象)的时候触发
功能: 查看对象
参数: 一个self接受当前对象
返回值: 必须返回字符串类型
注意点: 在try .. except .. as e中, 直接print(e)会打印错误对象的内容, 就是触发了__str__
__repr__
触发时机: 使用repr(对象)的时候触发
功能: 查看对象, 与魔术方法__str__相似
参数: 一个self接受当前对象
返回值: 必须返回字符串类型
__bool__
触发时机:使用bool(对象)的时候自动触发
功能:强转对象
参数:一个self接受当前对象
返回值:必须是布尔类型
__complex__(self), __int__(self), __float__(self)...
计算操作
__add__
触发时机:使用对象进行运算相加的时候自动触发
功能:对象运算
参数:二个对象参数
返回值:运算后的值
注意点: 同时有__add__ 和__radd__时, 先触发前者
减__sub__(self, other), 乘__mul__(self, other), 除__truediv__(self, other)...
元素操作
__len__
触发时机:使用len(对象)的时候自动触发
功能:用于检测对象中或者类中某个内容的个数
参数:一个self接受当前对象
返回值:必须返回整型
程序: 获取自定义成员数
迭代__iter__(self), 翻转__reversed__(self), 包含__contains__(self, item)
魔术属性
__dict__
获取对象或类的内部成员结构, 返回字典
不包括父类成员
类没有__init__, 那么实例化对象没有成员
__doc__
获取对象或类的内部文档, 跟help()方法同功能
__name__
获取类名或函数名, 返回字符串
__class__
获取当前对象所属的类, 返回type
__bases__
获取一个类直接继承的所有父类, 返回元组
程序错误
语法错误
代码没有按python规定写
SyntaxError: ...
异常错误
常见异常
IndexError
索引超出序列的范围
KeyError
字典中查找一个不存在的关键字
NameError
尝试访问一个不存在的变量
IndentationError
缩进错误
AttributeError
尝试访问未知的对象属性
StopIteration
迭代器没有更多的值
AssertionError
断言语句(assert)失败
其他常见错误
异常处理
基础语法
try .. except .. 抑制报错
功能
try代码块有报错就会执行except代码块, 否则不执行
注意
有多个错误时, 走第一个报错选项
扩展
BaseException是所有异常类的父类
Exception是常规异常类的父类
带有分支的异常处理
多个except分支
从上到下, 走第一个报错的
同一个except分支多个异常类型
从左到右, 走第一个报错的
捕获错误并输出报错内容
except StopIteration as e:
print(e)
其他写法
try .. except .. else ..
try .. finally ..
try .. except .. else .. finally ..
主动抛异常
raise + 异常错误类 / 异常错误对象, 主动触发异常, 程序直接报错停止运行
程序: 模拟系统抛出异常
函数
基本概念
概念
包裹一部分代码,实现某一个功能
特点
可以反复调用,提高代码的复用性,提高开发效率,便于维护管理
格式
def 函数名():
code1
code2
函数名()
命名
命名规则同变量
驼峰命名法
1) 大驼峰命名法:每个单词首字母大写(类的命名)
mycar => MyCar
2) 小驼峰命名法:首个单词首字母小写,其他单词首字母大写
mycar => myCar
_命名法
可以将不同的单词用_拼接在一起
symmetric_difference()
函数的参数
参数:函数运算时需要的值
参数种类
形参
形式参数,在函数的定义处
实参
实际参数,在函数的调用处
常见用法
位置参数
即普通形参和普通实参,位置顺序逐一对应
默认形参
如果有实参,那么使用实参。
如果没有实参,那么用形参的默认值
普通形参 + 默认形参
普通形参必须放在默认形参前,否则报错
关键字实参
如果都是关键字实参,可以任意调整实参的顺序
普通实参必须写在关键字实参的前面
收集形参
普通收集形参
专门收集多余的普通实参,并打包为元组
func(*args)
关键字收集形参
专门收集多余的关键字实参,并打包为字典
func(**kwargs)
收集所有参数
def func(*args, **kwargs):
pass
命名关键字参数
在调用函数时,必须使用关键字实参的形式来进行调用
(1) def func(a, b, *, c, d) 跟在*号后面的c和d是命名关键字参数
(2) def func(*args, e, **kwargs) 加在*args和**kwargs之间的参数都是命名关键字参数
星号的使用
*和**,在函数的定义处,负责打包(把实参都收集过来,放在元组或字典中)
*和**,在函数的调用处,负责解包(把容器类型的数据,一个一个拿出来,进行传递)
形参声明的位置顺序
普通参数 -> 默认参数 -> 收集参数 -> 命名关键字参数 -> 关键字收集参数
return
概念
把函数内部的数据返回到函数的调用处
return + 六大标准数据类型,此外,还可以返回 函数 或 类对象
return 在执行时意味终止函数,后面代码不再执行
如果不定义return返回值,默认返回None
全局变量和局部变量
全局变量
在函数外部定义的变量或者在函数内部使用global关键字声明
局部变量
在函数内部定义的变量
作用域
全局变量的作用范围横跨整个文件,函数内能引用但不能直接修改
局部变量的作用范围仅仅在函数的内部,函数外不能引用
生命周期
该变量的作用时长
内置命名空间:append, pass,,print...
全局命名空间:func,全局变量...
局部命名空间:局部变量
内置命名空间->全局命名空间->局部命名空间 (开辟空间顺序)
内置属性 > 全局属性 > 局部属性(生命周期:从长到短)
global的使用
若当前不存在全局变量,可以在函数内部通过global关键字定义
若当前存在全局变量,想要在函数内部修改并全局生效,先global一下
函数名的使用
动态创建
动态销毁
当参数传递
作为值返回
作为容器型数据的元素
__doc__或者help查看文档
在函数名之下可以写多行注释说明,能用help()和__doc__查看
函数的嵌套
概念
互相嵌套,外层的为外函数,内层为内函数
LEGB原则
找寻变量的调用顺序采用LEGB原则(就近原则)
nonlocal的使用
用来修改局部变量
nonlocal一个变量,遵循LEGB原则
nonlocal只能修改局部变量
容器型的局部变量可以不通过nonlocal修改,因为传的是地址
闭包
概念
互相嵌套的两个函数,1.如果内函数使用了外函数的局部变量,2.并且外函数把内函数返回出来,这个过程叫做闭包,里面的内函数叫做闭包函数
可以使用__closure__, cell_contents 判断闭包
闭包特点
内函数引用了外函数的局部变量,会延长该变量生命周期
闭包意义
可以优先使用外函数中的变量,对闭包中的值起到了封装保护的作用,外部无法访问
示例: 求最后结果
匿名函数lambda
概念
用一句话来表达只有返回值的函数
语法
lambda 参数:返回值
特点
简洁,高效
无参的lambda
lambda: "abc"
有参的lambda
lambda n: n * 3
三元运算符
只用于双向分支
语法
真值 if 条件表达式 else 假值
条件表达式True,返回if前面的值,反之,返回else后面的值
有判断条件的lambda
lambda m, n: m if m > n else n
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
语法
map(func, iterable)
功能
处理数据
把iterable的数据一个一个传给前面的func处理
参数
func:函数(内置函数,自定义函数)
iterable:可迭代对象(容器型数据,range对象,迭代器)
返回值
迭代器
示例一:列表中的纯数字字符串变为整型
示例二:列表的数分别左移得到另一组数
示例三:处理列表得到有映射关系的另一组数据
reduce
语法
reduce(func, iterable)
功能
计算数据
把前两个数据用func运算后,把结果与第三个元素运算,重复
参数
func:自定义函数
iterable:可迭代对象(容器型数据,range对象,迭代器)
返回值
计算的结果
示例一:多个数字组合为一个数
示例二:纯数字字符串不用int变为纯数字
filter
语法
filter(func, iterable)
功能
过滤数据
返回执行结果为True的入参
参数
func:自定义函数
iterable:可迭代对象(容器型数据,range对象,迭代器)
返回值
迭代器
示例:过滤奇数保留偶数
sorted
语法
sorted(iterable, key=函数, reverse=False)
功能
排序数据
参数
iterable:可迭代对象(容器型数据,range对象,迭代器)
key :指定函数(自定义/内置)
reverse :是否倒序
返回值
列表
示例一:按绝对值从小到大进行排序
示例二:按自定义函数进行排序
与sort的区别
可以排序所有的容器类型数据,sort只能处理列表
返回一个新的列表,sort会改变原列表
推导式
概念
通过一行循环判断遍历出一系列数据
语法
val for val in iterable
列表推导式
推导式基本语法
lst = [i * 2 for i in range(1, 6)]
带有判断条件的推导式
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
语法
enumerate(iterable, [start=0])
功能
枚举,将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数
iterable:可迭代对象(容器型数据,range对象,迭代器)
start:可以选择开始的索引号(默认从0开始索引)
返回值
迭代器
示例:把列表转为字典
zip
语法
zip(iterable, ... ...)
特点
按照索引配对
功能
将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数
iterable:可迭代对象(容器型数据,range对象,迭代器)
返回值
迭代器
示例一:把多个容器组合为字典
示例二: 可滑动序列
生成器
概念
就是允许自定义逻辑的迭代器
迭代器和生成器区别
迭代器本身是系统内置的,重写不了,而生成器是用户自定义的,可以重写迭代逻辑
创建方式
生成器表达式
里面是推导式,外面用圆括号
gen = (i for i in range(100))
生成器函数
yield
类似return,不过每次在返回值后会记住该位置,再调用时从此处往下走
基本语法
优化生成器代码
一般用for + next,选择一个范围调用,防止处理大数据耗时太久
send的使用
不仅调用,还给上一个yield发值,覆盖其在生成器中后续再使用的值
send,对比next,不但能取值,还能发送值
第一个 send 不能给 yield 传值 默认只能写None
最后一个yield 接受不到send的发送值
示例:一个能被调用三次的生成器
yield from的使用
将一个可迭代对象变成一个迭代器返回
斐波那契数列
使用生成器分段获取所有内容,而不一次把所有数据全部打印
示例: 求最后结果
递归函数
线性递归
概念
自己调用自己的函数, 叫做递归函数
递是去, 归是回来, 一去一回叫递归
栈帧空间
每次调用函数都要在内存中开辟空间, 叫做栈帧空间
总结
递归就是不断开辟与释放栈帧空间的过程
递归触发归的两种情况
最后一层栈帧空间执行结束
遇到return终止当前函数
递归不能无限开辟空间, 可能造成内存溢出
所以一定要给出跳出的条件
官方最大能开辟1000层, 太多层不推荐使用
开辟的栈帧空间数据彼此独立不共享
经典示例一: 阶乘
经典示例二: 斐波那契数列
经典示例三: 青蛙跳台阶
尾递归
概念
自己调用自己, 且返回的非运算表达式, 只有函数本身
特点
尾递归只开辟一个空间, 在一个空间里持续计算最后结果进行返回
写法
所有运算都是在函数中计算完毕, 通过参数传给下一次递归, 最后返回这个参数
经典示例一: 尾递归实现阶乘
优化一: 设默认值
优化二: 设默认值 + 隐藏该值
优化三: 默认值改为局部变量, 闭包保护该值
经典示例二: 尾递归实现斐波那契数列
内存栈区堆区(了解)
装饰器
概念
在不改变原有代码的前提下, 为原函数扩展新功能
函数装饰器
装饰器原型
调用被装饰函数时, 把它作为参数传给装饰器函数kuozhan(), kuozhan()是一个闭包结构, 会直接返回里面的wrapper, 在闭包函数wrapper()内执行被装饰函数和其他新增功能, 返回想要的结果
@符号
装饰器的标识符
自动把下面修饰的原函数当成参数传递给装饰器
把返回的新函数去替换原函数
装饰器嵌套
装饰器的执行顺序是从下到上依次进行功能的扩展
带有参数的装饰器
原函数和新函数参数和返回值要保持一一对应
带有参数返回值的装饰器
参数: 还是一一对应, 写上形参接收, 也可以用*全收集
返回值: 最后的返回值是wrapper的返回值
放在类中的装饰器
若装饰器在类中, 可以通过类访问成员的方式取出来放在@后, 也可以把类当作函数调用, 触发__call__, 返回出装饰器函数
带有参数的函数装饰器
可以通过传参选择不同的wrapper, 只要在装饰器外再包上一个函数, 判断参数来调用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)
max(dic, key=func) 自定义函数,处理前面的序列数据
pow()
求乘方
若三个参数,前两个乘方与第三个数取余
pow(2,3,7)
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()
将字符串当作python代码执行
功能更强大
repr()
不转义字符输出字符串
input()
接收输入字符串
hash()
生成hash值
可用与加密和文件校验
数学模块 math
ceil()
向上取整 (对比内置round)
math.ceil(-3.45)
floor()
向下取整 (对比内置round)
math.floor(3.99)
pow()
乘方 (结果为浮点数) (对比内置pow)
必须是两个参数
math.pow(2, 3)
sqrt()
开平方 (结果浮点数)
math.sqrt(9)
fabs()
绝对值 (结果浮点数) (对比内置abs)
math.fabs(-1)
modf()
将一个数拆成整数和小数组成元组
math.modf(3.897)
copysign()
复制参数2的符号给参数1 (返回一个小数)
math.copysign(-12, -9.1)
fsum()
求和 (结果浮点数)(对比内置sum)
math.fsum(lst)
pi
圆周率常数
math.pi
随机模块 random
random()
获取随机0-1之间的小数(左闭右开)
random.random()
randrange()
range的随机模式 (包含开始值,不包含结束值,间隔值)
randint()
获取指定范围的随机整数 (了解)
random.randint(3,5,1) # error
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 -> \n,window->\r\n 或 \n
路径模块 os.path
basename()
返回文件名部分
os.path.basename(pathvar)
dirname()
返回路径部分
os.path.dirname(__file__)
split()
将路径拆成文件和路径部分,组成一个元组
os.path.split(__file__)
join()
将多个路径拼成新的路径,自动加不同系统的斜杠
os.path.join(path1, path2, path3)
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()
重命名,os.rename("test1.txt", "test2.txt")
makedirs()
递归创建文件夹,os.makedirs("a/b/c/d")
removedirs()
递归删除文件夹(空文件夹),os.removedirs("a/b/c/d")
shutil 复制/移动
copyfileobj()
复制文件对象
copyfileobj(fsrc, fdst[, length=16*1024])
copyfile()
仅复制文件内容,底层调用了copyfileobj
copyfile(src, dst)
copymode()
复制文件权限,不包括内容
要先有文件
copystat()
复制所有状态信息,不包括内容
copy()
复制文件权限和内容
copy(src, dst),dst可以是目录或文件
copy2()
复制文件权限、内容和状态信息
copytree()
拷贝文件夹里所有内容(递归拷贝)
copytree(src, dst),不能覆盖dst
rmtree()
删除当前文件夹及其中所有内容(递归删除)
move()
移动文件或者文件夹,可以重命名
shutil.move("7.py", "test/8.py")
压缩模块
zipfile
zipfile.ZipFile()
默认只打包,要压缩则传参zipfile.ZIP_DEFLATED
压缩文件
用ZipFile以w模式打开压缩包对象,用write添加内容,用close关闭
解压文件
r模式打开
zf.extractall(路径)
zf.extract(文件, 路径)
追加文件
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 条评论
下一页