二、python学习-函数
类型判断
1.type()直接获取类型
2.isinstance
用法一:isinstance(值,类型) 返回真或假
用法二:isinstance(值,(类型1,类型2 ...)) 有一个类型满足 返回真
int float bool complex str list tuple set dict
1. 代码块
定义:以冒号作为开始,用缩进划分作用域
作用域:作用的范围
2. 单 双 多项分支
语法结构
单项:
if 判断表达式 :
代码块
双项:
if 判断表达式 :
代码块
else :
代码块
多项:
if 判断表达式 :
代码块
elif 判断表达式:
代码块
elif 判断表达式:
代码块
else 判断表达式:
代码块
巢状分支:
if 判断表达式 :
if 判断表达式 :
代码块
elif 判断表达式:
if 判断表达式 :
代码块
else :
代码块
else 判断表达式:
代码块
3. 循环结构
3.1 while循环
语法结构:
while 判断表达式 :
代码块
3.2 for循环
语法结构:
for ... in 容器:
代码块
range对象(配合for循环使用)
range(start,end,step)
start: 开始值
end: 结束值(最大值获取不到,获取到end-1)
step: 步长
3.3 pass,break,continue
- pass : 通过当前逻辑
- break: 循环结构中使用,结束当前层级循环
- continue: 跳出当前循环
4. 字符串的相关用法
- 字符串的拼接
- 字符串的重复
- 字符串的跨行拼接
- 字符串的索引
- 字符串的切片: 语法=》字符串[::] 完整格式[开始索引:结束索引:间隔值]
- [开始索引:]从开始索引截取到字符串的最后
- [结束索引:]从开头截取到结束索引之前(结束索引-1)
- [开始索引:结束索引] 从开始索引截取到结束索引之前(结束索引-1)
- [开始索引:结束索引:间隔值] 从开始索引截取到结束索引之前按照指定的间隔
- [:] 或 [::] 截取所有字符串
4.1 相关函数
- capitalize() 首字符大写
- title() 每个单词首字母大写
- upper() 所有字母大写
- lower() 所有字母小写
- swapcase() 大小写互换
- len() 字符串长度
- count() 统计字符号中某个元素的数量
- find() 查找某个字符串第一次出现的索引位置
- index() 与find功能相同 find找不到返回-1 index找不到数据直接报错
- startswith 判断是否以某个字符或字符串开头
- endSwith 判断是否以某个字符或字符串结尾
is系列
isupper() 判断大写
islower() 判断小写
isdecimal() 判断数字组成,必须纯数字
split() 按某字符划分成列表(默认字符是空格)
join() 按某字符讲列表拼接成字符串(默认容器都可以)
center() 填充字符串,原字符串居中(默认填充空格)
strip() 默认去掉首尾两边的空白符
replace() 替换字符串
4.2 format格式化字符串
{} 代表占位符
1.顺序传参
"{}是{}".format("a","b")
2.索引传参
"{1}是{0}".format("b","a")
3.关键字传参
"{a}是{b}".format(a="a",b="b")
4.容器类型数据(列表或元组)传参
下标:
"{0[0]}是{1[0]}".format(["a","b"],("c","d"))
关键字:
"{listvar[0]}是{tuplevar[0]}".format(listvar=["a","b"],tuplevar=("c","d"))
字典:字典在format中,键不需要加引号获取
"{dictvar1[a]}是{dictvar2[c]}".format(dictvar1={"a"="aa","b"="bb"]},dictvar2={"c"="cc","d"="dd"})
format填充字符串
^原字符串居中
>原字符串居中
<原字符串局左
例子:(who:!<10)
who : 关键字
! : 要填充的字符
< : 填充的方向,原字符串居左
10 : 字符串的总长度
总长度10 = 原字符串长度+填充字符串的长度
进制转换等特殊字符的使用(:d :f :s :,)
1. :d 整形占位符(要求必须是整型)
"{:d}月{:d}号".format(3,8) = 3月8号
"{:2d}月{:2d}号".format(3,8) = 3月 8号
"{:<2d}月{:<2d}号".format(3,8) = 3 月8 号
2. :f 浮点型占位符(要求必须是浮点型)
"{:f}元".format(9.9) = 9.9元
:02f保留两位小数,存在四舍五入
"{:.2f}元".format(98.319) = 98.32元
3. :s 字符串占位符(要求必须是字符串)
"{:s}".format("cascacsa")
4. :, 金钱占位符
"{:,}".format(123456789) = 123,456,789
5.列表的相关操作
1.列表的的拼接(同元组)+
2.列表的重复(同元组)*
3.列表的切片(同元组) **语法=》列表[::] 完整格式[开始索引:结束索引:间隔值]**
1. [开始索引:]从开始索引截取到列表的最后
2. [结束索引:]从开头截取到结束索引之前(结束索引-1)
3. [开始索引:结束索引] 从开始索引截取到结束索引之前(结束索引-1)
4. [开始索引:结束索引:间隔值] 从开始索引截取到结束索引之前按照指定的间隔
5. [:] 或 [::] 截取所有列表
4.列表的获取(同元组)
5.列表的修改(可切片)
#利用切片进行修改(切一段,放进去所有值)
#修改数据的要求是》可迭代数据(list set tuple dict range 迭代器)
lst = [a,b,c,d,e,f,g]
lst[1:3] = [bb,cc]
lst[1:3] = [bb,cc,sa,ww]
#带有步长的切片修改(切几个改几个)
lst[::2] = [aa,cc,ee,gg]
6.列表的删除(可切片)
#批量删除,
lst = [a,b,c,d,e,f,g]
del lst[1:4] => [a,e,f,g]
5.1 列表相关函数
tuple 只有两个方法,count index
列表:lst = [a,ca,rr,cd]
#增
1. append()想列表的末尾添加新的元素
lst.append(b)
2. insert()在指定索引之前插入元素
lst.insert(0,c)
3. extend()迭代追加所有元素,批量插入
tup = (e,d,c)
lst.extend(tup)
#删
1. pop 通过制定索引删除元素,没有索引移除最后一个,返回删除后的列表
res = lst.pop() => [a,ca,rr]
res = lst.pop(1) => [a,rr,cd]
2. remove() 通过指定的只删除,多个相同元素,默认删除第一个,无返回值
lst.remove(a)
3. clear()清空列表
lst.clear()
#改查
1. index()获取某个值在列表中的索引
res = lst.index(a)//当值不存在时,报错
2. count() 计算某个元素出现的次数
3. sort 列表排序(默认从小到大排序)
lst.sort()//小-》大
lst.sort(reverse=true)//大-》小
// 对字符进行排序,默认按照ASCLL字符编码进行排序,大小写字母ascll差值是32
// 字母比较是一位一位进行比较,如果第一位相同,再去比较第二位
// 编码升级 unicode => utf-8
// 中文进行排序,中文使用三个字节存储到计算机底层,无规律可行,实际是按照二进制进行排序
4. reverse()列表反转操作,水平反转
lst.reverse() => [cd,rr,ca,a]
5.2 深拷贝 和 浅拷贝
a = 19
b = a
a = 20
print(b) => 19
lst1 = [1,2,3]
lst2 = lst1
lst1.pop(4)
print(lst2) => [1,2,3,4]
//浅拷贝
#方法一
lst1 = [1,2,3]
lst2 = lst1.copy()//只拷贝一级,其他层级保留元数据
lst1.pop(4)
print(lst1) => [1,2,3,4]
print(lst2) => [1,2,3]
#方法二
import copy
lst1 = [1,2,3]
lst2 = copy.copy(lst1)
lst1.pop(4)
print(lst1) => [1,2,3,4]
print(lst2) => [1,2,3]
//深拷贝语法 针对多级容器,所有层级元素都单独拷贝一份,形成独立的副本
#方法一
lst1 = [1,2,3,[4,5]]
lst2 = copy.deepcopy(lst1)//只拷贝一级
lst1[-1].pop(6)
print(lst1) => [1,2,3,[4,5,6]]
print(lst2) => [1,2,3,[4,5]]
#总结
copy 比较 deepcopy 比较 copy更快
**浅拷贝:只拷贝第一层所有的元素,copy.copy()**
**深拷贝:为所有层级的元素都单独开启新的空间 copy.deepcopy*()*
(地址:不可以变数据都暂时指向,可变数据都是单独开辟空间)
6.字典相关函数
#增
dic = {}
dic["a"] = ["啊"]
dic["b"] = ["把"]
dic["c"] = ["出"]
#fromkeys() 使用一组键和默认值创建字典
dic = {}.fromkeys([a,b,c],None)//批量赋值容器类型为同一地址的元素
#删
#pop() 通过键去删除键值对(没有该键设置默认值,预防报错)
dic.pop("a")
dic.pop("dd","没有")
#popitem() 删除最后一对键值对
dic.popitem()
#clear() 清空字典
#改
#update() 批量更新,有键就更新,无键就添加
newdic = {"a":"啊啊","d":"的"}
dic.update(newdic) => a:啊啊 b:把 c:出 d:的
# 方法二dic.update("a":"啊啊","d":"的") 不推荐
#查
#get() 通过键取值,(没有键可以设置默认值,预防报错)
dic["aa"] => 报错
dic.get("aa") => None
dic.get("aa","") => ""
# 可迭代对象:容器类型数据,range对象。迭代器
#keys() 讲字典的键组成新的可迭代对象
dic.keys() => dict_keys(["a","b","c"])
dict_keys 可迭代对象,没有具体类型
#values() 将字典中的值组成新的可迭代对象
dic.values() => dict_values(["啊","把","出"])
#items() 讲字典中的键值对组成一个个元组,组成新的可迭代对象
res = dic.items () => dict_itemys([("a","啊"),("b","把"),("a","出")])
#变量的解包
for k,v in res:
print(k,v)
7.集合的相关操作和函数
作用:用来交差并补集用,默认去除重复数据
补集只存在一个集合被另一个集合完全包涵的情况中
set1={a,b}
set2={b,c}
# intersection() 交集
set1.intersection(set2)
# 简写 &
set1 & set2
# difference() 差集
set1.difference(set2)
# 简写 -
set1 - set2
# union() 并集
set1.union(set2)
# 简写 |
set1 | set2
# symmetric_difference() 对称差集(补集包涵在在中)
set1.difference(set2)
# 简写 ^
set1 ^ set2
# issubset() 判断是够是子集
# 简写 <
# issuperset() 判断是够是父集
# 简写 >
# isdisjoint() 判断量几个是否不相交 不:true 相交 false
7.1 集合相关的函数
# 增 add() 批量添加 update()
# 删
clear()清空
pop()随机删除一个
remove()删除指定的值 不存在报错
discard()删除指定的值 不存在不删除 推荐
# 改 update()
# 查
7.2 冰冻集合
# frozenset 可强转容器类型数据编程冰冻集合
特征:不能做任何添加 删除,只能交叉并补, 可遍历
空的冰冻集合:frozenset()
8.文件操作
# 文件写入步骤
a.打开文件--把冰箱打开
fp = open(文件名=r"e:\py\20210306\a.txt",mode=模式,encoding=字符编码集)
fp 文件的io对象(文件句柄)
i : input 输入
o : output 输出
模式:w write写入 r read读取 a append追加
b.写入
fp.write("把大象塞进去")
c.关闭--把冰箱关闭
fp.close()
# 文件读取步骤
a.打开文件--把冰箱打开
fp = open(文件名=r"e:\py\20210306\a.txt",mode=模式,encoding=字符编码集)
fp 文件的io对象(文件句柄)
i : input 输入
o : output 输出
模式:
w write写入
不存在创建,存在清空,并将文件指针放在文件的结尾
r read读取
不存在报错,存在打开,并将文件指针放在文件的开头
a append追加
不存在创建,存在打开,并且将文件指针放在文件的末尾
xar异或模式
b.写入
res = fp.read() ->大象
c.关闭--把冰箱关闭
fp.close()
# 扩展功能(配合打开模式的辅助模式,自己不能单独使用)
+ puls 增强模式(可以让文件具有读写功能)
--> w w+ wb wb+
r r+ rb rb+
a a+ ab ab+
b bytes bytes模式(二进制字节流)用来传输或者存储的数据
--> b"111"要求:b开头的字符串,内容必须是ascii编码
# 字符串 字节流类型转换
#encode(字符串编码="utf-8") 编码 字符串->bytes
#decode(字符串编码="utf-8") 解码 bytes->字符串
#len()计算字节流长度
# 存储字节流(场景:图片、音频、视频等存储)
wb 与 rb 来存储二进制字节流
///字节流模式下,不需要指定编码集
fp = open("test.txt",mode="wb")
bytesstr = "阿克苏不参加".encode("utf-8")
fp.write(bytesstr)
fp.close()
fp = open("test.txt",mode="rb")
fp.read()
fp.close()
8.1 字符
字符:无论是神马语言,独立的一个文字就是字符
存储单位:
Byte字节
bit:位
1B = 8b
B:字节 ,1Byte = 8bit
字符大小:
英文和数字都是一个字节,汉 韩 日文等采用多个字节存储
GB系列编码:村吃一个汉字使用2个字节
UTF系列:存储一个汉字使用3个字节
字符编码种类:(把编码看成一个密码集,每一个字符在计算机中都是二进制)
英文原始编码:
ASCII码-》最早的字符编码格式,仅支持英文以及特殊符号
中文编码:
GB2312: 5000常用汉字
GB18830: 15888个汉字
GBK: 所有汉字编码
BIG5: 繁体中文编码
万国码:
unicode: 世界上所有的文字(文论神马字符都按照4个字节表示)
UTF-8 : 可变长的unicode编码
8.2文件的扩展模式
1.r+模式,文件指针默认在文件开头
# r+ 先读后写
fp = open("ceshi.txt","r+","utf-8")
//先读
res = fp.read()
//后写
fp.write("123")//写完默认文件光标在末尾的位置
//先把文件光标移动到开头
fp.seek(0)
//再读
res = fp.read()
fp.close()
# r+ 先写后读
fp = open("ceshi.txt","r+","utf-8")
//先写 r模式默认把文件指针在文件开头位置
//先把文件光标移动到末尾
fp.seek(0,2)
fp.write("abc")//写完默认文件光标在末尾的位置]]
//后读
fp.seek(0)
res = fp.read()
2.w+模式 可读可写
fp = open("ceshi.txt","w+","utf-8")
//先写 w模式默认把文件指针在文件末尾位置
fp.write("abcascacc")//写完默认文件光标在末尾的位置]]
//后读
fp.seek(0)
res = fp.read()
fp.close()
3.a+模式 append模式强制把文件指针在文件末尾位置
#a模式 w模式默认都可创建文件
#a模式下:seek移动文件指针后插入内容,文件指针还是默认在文件末尾位置
fp = open("ceshi.txt","a+","utf-8")
fp.write("11122")
fp.seek(0)
res = fp.read()
fp.close()
8.3文件的主要功能
(utf-8:默认中文=3Byte 英文|符号=1Byte)
# 1.read(字符) 功能: 读取字节的个数(里边的参数代表字符的字数)
# 2.seek(字节数,方向 2结尾 1开头) 功能:调整指针的位置(里边参数代表从文件开头调整光标位置的字节数)
# 3.tell() 功能: 计算当前光标位置至最左边位置的字节总数
123xxx456
fp = open("ceshi.txt","r+","utf-8")
fp.read(6) => 123xxx
fp.seek(2) => 12光标所在3xxx456
fp.read(2) => 3x
fp.tell() => 4个字节
123今天天气456
fp = open("ceshi.txt","r+","utf-8")
fp.seek(5)
fp.read()=>报错,seek移动的是字节数,decode反解失败
# with语法(省略close操作)相当于执行了close
with open(...) as fp:
fp.write("caca")
with open(...) as fp, open(...) as fp1:
fp.write("caca")
fp1.write("caca1")
# 4.刷新缓冲区 flush()手动方法
当文件关闭时候自动刷新缓存区
当程序运行结束的时候自动刷新缓存区
当缓存区写满,自动刷新缓存区
手动刷新缓存区
# close的意义
fp = open("ceshi.txt","a+","utf-8")
fp.write("caca")
while true:
pass
fp.close()
fp.flush()//刷新缓存区
8.4 文件相关函数
1.readable() 判断文件对象是否可读
2.writable() 判断文件对象是否可写
3.readline(读取的字符个数) 读取一行文件内容
4.readlines() 将文件中的内容按照换行读取到列表中
"""
csacsa
ascasc
cascas
avavav
"""
lst_new = []
with open("ceshi.txt","r+","utf-8") as fp:
lst = fp.readlines()
for i in lst:
i.strip()
lst_new.append(i)
5.writelines() 将内容是字符串的可迭代行数据写到文件中
lst_new1 = []
with open("ceshi.txt","w+","utf-8") as fp:
lst_new.insert(3,"cacasca")
for i in lst_new:
res = i + "\n"
lst_new1.append(i)
fp.writelines(lst_new1)
6.truncate() 把要截取的字符串提取出来,然后清空内容讲提取的字符串重新写入文件中(字节)
截取-》清空-》重写 单位字节
9.函数
9.1 函数格式特点
函数:功能
特点:
基本格式:
定义
def func():
code..
调用
func()
函数命名:
字母数字下划线,首字符不能为数字
严格区分大小写,切不能使用关键字
函数命名有意义,且不能使用中文
驼峰命名法:
1.大骆驼:每个单词首字符大写(面向对象中,定义calss)
2.小驼峰:处理第一个单子小写,剩下每个单词首字符大写(函数,变量)
9.2 函数参数
函数参数:
1.形参:形式上的参数,在函数的定义处
普通,默认,普通收集,命名关键字,关键字收集
2.实参:实际上的参数,在函数的调用处
普通,关键字
默认形参 和 关键字实参区别:默认行参在函数的定义处,关键字实参在函数的调用处
参数的顺序
#形参顺序
普通-》默认-》普通收集-》命名关键字-》关键字收集
#收集所有实参
def func(*args,**kwargs):
pass
收集参数
收集参数:
1.普通收集参数:收集多余的没人要的普通实参,构成**元组**
参数前面加上*,代表是普通收集参数
def func(*args):
pass
args => arguments(参数)
2.关键字收集参数:收集多余的没人要的关键字实参,构成一个**字典**
参数前面加上**,代表关键字收集参数
def func(**kwargs):
pass
kwargs = keyword arguments
def func(a,b,**k)
func(1,2,c=3,d=4)
关于*与**的使用方法:控制了参数的个数,解耦代码
在函数定义处,*和**用来接收数据,*打包成元组,**打包成字典
在函数调用处,*和**用来解包数据,*一般应用在列表或元组,**一般用在字典
func(1,2,c=3,d=4)
# *在调用处用法
lst=[1,2]
func(*lst,c=3,d=4)
# **在调用处用法
dic = {"c":3,"d":4}
func(1,2,**dic)
func(*lst,**dic)
命名关键字参数
def func(参数1,参数2,*,参数3)
定义:在*后后面定义的参数是命名关键字参数
def func(*args,参数,**kwargs)
在普通收集与关键字收集参数之间,也是命名关键字参数
例子:
1.def func(a,b,*,c):
pass
func(1,2,c=3)
2.def func(*args,dd,**kwargs):
pass
func(1,2,3,dd=111,a=1,b=2,c=3)
9.3 函数返回 return
return:函数可以自定义返回值,通过return,可以把这个值返回到函数的调用处
1.return+返回值,后面可以接6打标准数据类型外,还可以返回函数和类对象,默认返回None
2.在函数中执行return,终止函数,后面代码不执行
10.全局变量_局部变量
局部变量:在函数内部定义的变量就是局部变量
全局变量:在函数外部定义的全量或者在函数内部用global关键字定义的全局变量
作用域:作用的返回
局部变量 在函数内部
全局变量 横跨整个文件
global:
函数外部有这个全局变量,在函数内部使用global,可以修改全局变量
函数内部无这个全局变量,在函数内部使用global关键字,可以定义全局变量
在函数内部可以直接获取全局变量,无法直接修改,需要通过global
f=1
def func():
f=2
print(f)=>2
func()
print(f) => 1
10.1命名空间
命名空间:划分一块区域保存所有数据,以字典方式存储(变量 值形成映射关系)共三种:
1.内建命名空间:解释器启动时创建,直到解释器运行结束,生存周期最长
2.全局命名空间:文件运行时创建,直到解释器运行结束,周期较长
3.局部命名空间:函数调用时,里边的变量才创建,调用结束后释放,周期较短
命名空间 创建顺序:python解释器启动-》内建命名-》全局命名-》局部命名
命名空间 销毁顺序:函数调用结束-》局部-》全局-》内建
10.2变量名
1.函数名是个特殊的变量,可以当成变量赋值
def func1():
retuurn 111
动态创建:
func=func1
func()
动态销毁函数
del func
func()=>报错
2.函数名可以作为容器类型数据的元素
def func2():
pass
def func3():
pass
def func4():
pass
lst = [func2,func3,func3]
for i in lst:
i()
3.函数名可以作为函数参数
def myfunc(f):
res =f()
myfunc(func4)
4.函数名可作为函数的返回值
def myfunc(f):
return f
f2 = myfunc(func4)=>打印出func4的内存地址
__doc__或者help查看文档
def func():
···
功能
参数
返回值
···
10.3 locals globals
locals:
如果在函数外,调用locals(),获取的打印之前的所有变量,返回字典,全局控件作用域
如果在函数内,调用locals(),获取的调用之前的所有变量,返回字典,全局控件作用域
globals:
如果在函数外,调用globals(),获取的打印之前的所有变量,返回字典,全局控件作用域
如果在函数内,调用globals(),获取的调用之前的所有变量,返回字典,全局控件作用域
globals特殊用法:
通过系统全局字典添加键值对,可以动态创建全局变量
自动创建变量,批量创建全局变量
dic = globals()
#传递字符串,创建变量
k = "guo"
dic[k] = "测试"
print(guo) ==> 测试
10.4 函数的嵌套
函数的嵌套:
嵌套在函数的外部叫外函数
嵌套在函数的内部叫内函数
def cuter():
def inner():
pass
1.内部函数可以在函数外部调用吗?不可以,作用域问题
2.调用外部函数后,内部函数可以在函数外部调用吗?不可以
3.内部函数可以在函数内部调用吗?可以
4.内部函数在函数内部调用时,是否有先后顺序?有,代码执行自上而下
python没有预加载,不会把函数预加载至内存中
LEGB原则(就近找变量原则)
B -- Builtin(python):python内置的命名空间 内建作用域
G -- Global(Module):函数内部所在的命名空间 全局作用域
L -- Local(function):当前函数内的作用域 局部作用域
依据就近原则,从下往上,从里向外,依次寻找
nonlocal关键字
global:用来修改全局变量
nolobal: 用来修改局部变量
遵循LEGB原则
1.用来修改当前作用域上一级的局部变量
例子:
def outer():
a=10
def inner():
nolocal a//提高作用域
a=20//作用域在inner
print(a)=>20
inner()
print(a)=>20
outer()
2.如上级找不到,继续向上寻找
def outer():
a=10
def inner():
nolocal a//提高作用域
a=20//作用域在inner
print(a)=>20
inner()
print(a)=>20
outer()
3.全部找不到,直接报错
a=10
def outer():
def inner():
nolocal a//提高作用域
a=20//作用域在inner
print(a)=>20
inner()
outer()
print(a)=>报错,a是全局变量
4.不使用nonlocal,是否可以修改局部变量
def outer():
lst = [1,2,42]
def inner():
lst[-1]=52
inner()
print(lst)
outer()
10.5 闭包函数
定义:
内函数使用了外函数的局部变量
外函数将内函数返回出来的过程,叫做闭包
里边的内函数叫闭包函数
1.闭包函数用法
def func():
father = "王健林"
def wjl_hobby()://闭包函数
print("acsacsa{}".format(father))
return wjl_hobby
res = func()
print(res)=>打印出函数地址
res()=>acsacsa王健林
2.升级
def func1():
father = "a"
jiejie = "b"
meimei = "c"
money = 1000
def jiejie_hobby()://二级闭包函数
nonlocal money
money -= 700
print("b%s" % (money))
def meimei_hobby()://二级闭包函数
nonlocal money
money -= 200
print("c%s" % (money))
def big_master()://闭包函数,
return [jiejie_hobby,meimei_hobby]
return big_marter()
func = func1()
func()[0]()=>b300
func()[1]()=>c100
** 获取闭包函数使用的变量 __closure__, cell_contents**
tup = func.__closure__//判断是否闭包,返回为空不是闭包
**cell_contents:获取单元格对象里边的内容**
jiejie =tup[0].cell_contents
meimei =tup[0].cell_contents
jiejie()=>b300
meimei()=>c100
闭包特点意义
** 闭包的特点:内函数使用了外函数的局部变量,该局部变量与内函数发生绑定,延长该变量的**生命周期
#例子:
def outer(val):
def inner(num):
return num + val
return inner
func = outer(5)
res = func(4) -> res=9
# 实参5 和 形参val 一一对应
# 因为内函数inner 和 val进行绑定,延长了val变量的生命周期,不释放
**闭包的意义:**
**闭包可以优先使用外函数的局部变量**
**局部变量在函数外部不能被直接使用**
**对局部变量实现了保护的作用,外部无法访问**
# 模拟鼠标点击
click_num = 0
def click_func():
global click_num
click_num +=1
print(click_num)
clock_func() 1
clock_func() 2
clock_func() 3
click_num = 100 #受到攻击
clock_func() 101
# 闭包模拟鼠标点击
def outer():
click_num = 0
def inner():
nonlocal click_num
click_num += 1
print(click_num)
return inner
clock_func = outer()
clock_func() 1
clock_func() 2
clock_func() 3
click_num = 100 #受到攻击
clock_func() 4
10.6匿名函数
只有返回值的函数,特点:简洁 高效 方便
** lambda表达式**
语法结构:
lambda 参数:返回值
种类:
1.无参的lambda表达式
def func():
pass
func()
改写 lambda:
func = lambda : pass
func()
2.有参的lambda表达式
def func(n):
return type(n)
func(17)
func = lambda n : type(n)
func(17)
3.带有判断条件的lambda表达式
def func(n):
if n%2 == 0:
return 0
eles:
return 1
func(17)->1
三元运算符:真值 if 条件表达式 else 假值
func = lambda n : 0 if n%2==0 else 1
func(17)->1
10.7 迭代器
能被next调用,并且不断返回下一个值的对象,叫做迭代器(迭代器是对象)
概念:迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果而继续,单纯的重复不是迭代
特点:不依赖索引。而是通过next指针迭代所有数据,一次只取一个,节省空间,迭代无限量数据
1.可迭代对象
## dir函数可以查看对象中所有的成员
## 如果成员中含有__iter__这个方法,就是可迭代对象
setvar = {"a",1,"b",2}
for i in setval:
print(i)
2.迭代器
## for循环遍历数据的底层实现就是利用了迭代器,通过next方法进行调用,杏儿获取数据
## 可迭代对象 和迭代器之间的关系:从不可被直接获取==?可被直接获取的过程
## 如果是一个迭代器对象,不一定是一个迭代器
## 如果是一个迭代器,就一定是一个可迭代性对象
2.1 如何定义一个迭代器
## iter(可迭代对象)
## 可迭代对象.__iter__()
例子:
it = iter(setval)
2.2判断一个迭代器
## 如果内置成员中,含有__iter__ 和 __next__两个方法,就可以判断是一个迭代器
res = "__iter__" in dir(it) and "__next__" in dir(it)
res =>true
2.3 如何调用一个迭代器
## next(迭代器)
## 迭代器.__next__()
## 迭代器通过next方法调用时,是单项不可逆的过程
next(it)
2.4 重置迭代器
it = iter(setvar)
res = next(it)
2.5 使用iterator 和 iterable 来判断是否是迭代器
"iterator 迭代器类型 iterable可迭代对象"
from collections import iterator,iterable
setvar = {a,b,c,d}
res = isinstance(setvar,Iterator)=>false
res = isinstance(setvar,iterable)=>true
# 判断range的迭代属性
it = iter(range(10))
res = isinstance(it,Iterator)=>true
res = isinstance(it,iterable)=>true
# 更多的调用方式
1.通过next获取迭代器中的数据
res = next(it)->0
res = next(it)->1
res = next(it)->2
...
2.通过for循环,遍历迭代器
for i in iter(range(10)):
print(i)
3.for 和 next配合调用迭代器
it = iter(range(100000000))
for i in range(10):
print(next(it))
10.8 高阶函数
能够把函数当成参数传递的就是高阶函数
map
map(func,iterable)
功能:
被iterable里边的数据拿出来,放到func函数进行处理,处理的结果丢到返回的迭代器中
参数:
func自定义函数 或者 内置函数
iterable 可迭代对象(容器类型数据 range 迭代器)
返回值:
迭代器
例子1:
要求:["1","2","3"]=>[1,2,3]
form collections import Iterator,Iterable
lst = ["1","2","3"]
it = map(int,lst)
res = isinstance(it,iterator)=>true
for i in it:
print(i)
# list强转迭代器
it = map(int,lst)
res = list(it) =>[1,2,3]
filter
filter(func,iterable)
功能:
在自定义的函数中,过滤数据
返回true,代表保留数据
返回false,舍弃该数据
参数:
func自定义函数 或者 内置函数
iterable 可迭代对象(容器类型数据 range 迭代器)
返回值:
迭代器
例子1:
要求:[1,2,3,4,5,6,7]=>要奇数
lst = [1,2,3,4,5,6,7]
it = filter(lambda n : false if n%2==0 else true,lst)
print(list(it))
reduce
reduce(func,iterable)
功能:
一次性从iterable中拿出两个值,丢到func函数中进行处理,
把运算结果再和iterable的第三个值继续丢到func中做运算
...依次类推
最后返回计算的结果
参数:
func自定义函数 或者 内置函数
iterable 可迭代对象(容器类型数据 range 迭代器)
返回值:
最后计算的结果
引用:from functools import reduce
例子:
要求[5,4,8,8] =>5488
from functools import reduce
lst = [5,4,8,8]
reduce(lambda x,y:int(str(x)+str(y)),lst)
reduce(lambda x,y:int(str(x)+str(y)),lst)
例子2:
要求:"789"=>789
strval = "789"
sorted
排序范围:元组,列表,集合,字符串,字典
sorted(iterable,reverse=true,key=函数)
功能:
排序
参数:
iterable 可迭代对象(容器类型数据 range 迭代器)
reverse 代表是否倒叙,true倒叙 false正序
key 自定义函数或内置函数
返回值:
排序后的结果
例子:
lst = [100,200,13,-6,0]
lst_new = sorted(lst,false)
#按照绝对值排序 abs内置函数
lst_new = sorted(lst,key=abs)
#按照自定义函数进行排序
lst = [19,27,45,48]
按照余数大小排列:
def func(n):
return n % 10
sorted(lst,key = func)=>[5,7,8,9]
总结:
sort 基于原有的列表进行排序,只限定列表类型
sort 所有的容器类型都能排序,返回一个全新的列表(推荐)
10.9 生成器函数
yield 类型于 return
共同点:执行到这句话都会把值返回出去
不同点:yield每次返回时,会记住上次离开时执行的位置,下次调用生成器,会从上次执行的位置往下走,而return会直接终止函数,每次重头调用
# 1.基本语法:
def mygen():
print(1)
yield 1
print(2)
yield 2
print(3)
yield 3
# 初始化生成器函数,返回生成器对象,简称生成器
from collections import Iterator
gen = mygen()//gen生成器对象 mygen生成器函数
ptint(isinstrance(gen,Iterator))=>true//生成器也是迭代器的一种
res = next(gen)
print(res)==>1
res = next(gen)
print(res)==>2
res = next(gen)
print(res)==>3
res = next(gen)
print(res)==>error
10.10 集合推导式
通过一行循环判断,遍历出一系列数据的方式就是推导式
推导式在使用时,只能用for循环和判断,判断只能是单向循环
语法:val for val in Iterable(把想要的值写for的左侧)
里边是一行循环判断,根据套在推导式外层的符号判断具体是神马类型的推导式
种类:
[val for val in Iterable] 列表推导式
{val for val in Iterable} 集合推导式
{a:b for a,b in Iterable} 字典推导式
例子:
lst = [i for i in range(1,51)]
1.普通推导式
# [1,2,3]=>[2,8,24]
lst = [ i * 2 ** i for i in lst]
lst = [ i << i for i in lst]
2.带有判断条件的推导式
lst = [1,2,3,4,5,6,7,8]
#求偶数
lst =[ i for i in lst if i % 2 ==0]
3.多循环推导式
lst1 = [1,2,3]
lst2 = ["a","b","c"]
#谁爱谁
lst = [ i+"爱"+j for i in lst1 for j in lst2]
4.带有判断条件的多循环推导式
#谁爱谁,判断索引相同才拼接
lst = [ i+"爱"+j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j)]
字典推导器
1.enumerate
enumerate(iterable,[start=0])
功能:枚举,将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:
iterable:可迭代性数据
start:可以选择开始的索引号,默认从0开始
返回值:迭代器
lst = ["a","b","c"]
it = enumerate(lst,start=1)
dict(it)=>{1:a,2:b,3:c}
# 通过推导器配合enumerate实现
dic = {k:v for k,v in enumerate(lst,start=1)}
zip
zip(iterable,...,...)
功能:将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:iterable
返回:迭代器
lst1 = [a,b,c]
lst2 = [1,2,3,4]
it = zip(lst1,lst2)
list(it)=>=>[(a,1),(b,2),(c,3)]
# 使用zip配合推导式实现
dic = {k:v for k,v in zip(lst1,lst2)}
10.11生成器
生成器本质是迭代器,允许自定义逻辑的迭代器
迭代器和生成器的区别:迭代器本身是内置的,重写不了,生成器是用户自定义的,,可以重写迭代逻辑
# 生成器可以用两种方式创建:
1.生成器表达式(里边是推导式,外表用圆括号)
2.生产器函数(用def定义,里边含有yield)
# 1.生成器表达式
gen = (i*2 for i in range(1,5))
# 2.生产器函数
# 初始化生成器函数->生成器对象-
def mygen():
for i in range(1,101):
yield "%s" % (i)
gen = mygen()//生成器对象 = 生成器对象
# 3.send
# send可以发送数据,发送给上一个yield
# 与next区别:next 只能取值,send能取值还能发送值
# send注意点:第一个send不能给yield传值,只能none,最后yield 接收不到send的发送至
def mygen()
print("开始")
res = yield 111
print(res)
res = yield 222
print(res)
res = yield 333
print(res)
print("结束")
gen = mygen()
# 第一个send不能给yield传值,只能none
val = gen.send(None)
print(val)=>开始 111
val = gen.send(444)
print(val)=> 开始 111 444 222
val = gen.send(555)
print(val)=> 开始 111 444 222 555 333
val = gen.send(666)
print(val)=> 开始 111 444 222 555 666 end 报错,没有
# 4. yield from :将一个可迭代对象变成一个迭代器返回
def mygen():
lst = [a,b,c]
yield from lst
gen = mygen()
print(next(gen))=>a
print(next(gen))=>b
print(next(gen))=>c
# 案例:斐波那契数列 1 1 2 3 5 8 13 21 34 55....
def mygen(maxlength):
a = 0
b = 1
i = 0
while i < maxlength:
yield b
a,b = b, a+b
i +=1
gen = mygen(50)
for i in range(10):
print(next(gen))
10.12 递归函数
递归函数,自己调用自己函数时递归函数
递归:去的过程,就是不听的开辟栈帧空间的过程,在回的时候,就是不断的释放栈帧空间
写递归函数,必须给出跳出的条件,层数过多不推荐使用
递归函数用每层空间都是独立的个体,独立的副本,资源不共享,可以通过return来完成值的传递
函数在运行时候,需要内存开辟空间(栈帧空间),调用结束释放空间
# 递归函数有回的过程,有两种情况可以出发:
# 1.当最后一层函数全部执行结束的时候,回到上层函数空间的调用处
# 2.遇到return返回值,直接返回上层空间的调用处
# 递归最大层数1000层,具体按照机器差异不同
尾递归(自己调用自己,并且非表达式)(把值放到参数中运算)
无论调用多少次函数,都只占用一份空间
只需要考虑最后一层空间的结果是多少,就不用额外考虑会的结果
在 cpython解释器中不支持尾递归,个别解释器支持
递归算法
二、python学习-函数的更多相关文章
- python学习-函数和lambda表达式(五)
5.2函数参数 位置参数:根据位置传入参数 关键字参数:根据参数名来传入参数 def girth(width, height): print("width:", width) pr ...
- python学习——函数及其参数
函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率.严格来说python只有函数,没有过程,人们理解的函数都是带有return的,而过程 ...
- 学以致用三十二-----python中函数的括号使用
一直以来对python中函数括号的使用,有点分不清楚,到底什么时候用括号,什么时候不用括号,造成了很大看困惑. 今天来总结下. class aaa(): y = 'you' def __init__( ...
- python学习——函数返回值及递归
返回值 return语句是从python 函数返回一个值,在讲到定义函数的时候有讲过,每个函数都要有一个返回值.Python中的return语句有什么作用,今天小编就依目前所了解的讲解一下.pytho ...
- python学习——函数进阶
首先来看下面这个函数. def func(x,y): bigger = x if x > y else y return bigger ret = func(10,20) print(ret) ...
- python学习——函数
一.在python的世界里什么是函数: 答:函数通常是用来实现某一个功能二被封装成的一个对象,是用来实现代码复用的常用方式 现在有一个需求,假如你在不知道len()方法的情况下,要你计算字符串‘he ...
- python学习——函数参数
一.为什么要使用函数 函数能提高应用的模块性,和代码的重复利用率. 二.函数的参数 位置参数:从左至右进行匹配 一般情况,也就是我们迄今为止最常用的方法,是通过位置进行匹配把参数值传递给函数头部的参数 ...
- Python学习-函数,函数参数,作用域
一.函数介绍 函数定义:函数时组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 我们已经知道python提供了许多内建函数,print(), type()等.我们也可以自己创建函数,这被叫 ...
- python学习 函数
# -*- config=utf-8 -*- #################################### 函数 ################################## de ...
随机推荐
- SSL/TLS协议详解(上):密码套件,哈希,加密,密钥交换算法
本文转载自SSL/TLS协议详解(上):密码套件,哈希,加密,密钥交换算法 导语 作为一名安全爱好者,我一向很喜欢SSL(目前是TLS)的运作原理.理解这个复杂协议的基本原理花了我好几天的时间,但只要 ...
- HTTP2 的前世今生
本文转载自HTTP2 的前世今生 导语 作为一名 Web 后端开发工程师,无论是工作中,还是面试时,对于 HTTP 协议的理解都是必不可少的.而 HTTP2 协议的发布更是解决了 HTTP1.1 协议 ...
- Flutter 中不得不会的 mixin
mixin 是 Dart 中非常重要的概念,对于未接触过此概念的Coder来说尤其重要,最近看源码的时候,由于对 mixin 不熟悉导致理解出现偏差,走了很多弯路,所以这篇文章介绍一下 mixin 概 ...
- Spring Boot和Thymeleaf整合,结合JPA实现分页效果
在项目里,我需要做一个Spring Boot结合Thymeleaf前端模版,结合JPA实现分页的演示效果.做的时候发现有些问题,也查了现有网上的不少文档,发现能全栈实现的不多,所以这里我就把我的做法, ...
- 第43天学习打卡(JVM探究)
JVM探究 请你谈谈你对JVM的理解?Java8虚拟机和之前的变化更新? 什么是OOM,什么是栈溢出StackOverFlowError? 怎么分析? JVM的常用调优参数有哪些? 内存快照如何抓取, ...
- 记录vue springboot 跨域采坑
vue配置 域名src\main.js要与config\index.js一样 var axios = require('axios')axios.defaults.baseURL = 'http:// ...
- molloc堆区的动态内存分配
[前言]前面有一篇文章介绍了堆区栈区的区别.栈区的核心主要集中在操作一个栈结构,一般由操作系统维护.堆区,主要是我们程序员来维护,核心就是动态内存分配. 这篇笔记结束就不在高新CSAPP的读书笔记了, ...
- RabbitMQ(一)安装篇
1. RabbitMQ 的介绍➢ 什么是 MQ?MQ 全称为 Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.➢ 要解决什么样的问题?在项目中,将一些无需即时返回且耗 ...
- SSAS表格模型
Analysis Services 是在决策支持和业务分析中使用的分析数据引擎 (Vertipaq) . 它为商业智能提供企业级语义数据模型功能 (BI) .数据分析和报告应用程序,如 Power B ...
- 基于Hi3559AV100 RFCN实现细节解析-(1)VGS初介绍
下面随笔系列将对Hi3559AV100 RFCN实现细节进行解析,因为RFCN用到了VGS加框,因此本篇随笔将给出VGS视频图像子系统的具体说明,便于后面RFCN的细节实现说明. VGS 是视频图形子 ...