python函数高级【内置函数和推导式】
1.函数嵌套
python中以函数为作用域,在作用域中定义的相关数据只能被当前作用域或子作用域使用
1.1函数在作用域中
函数也是定义在作用域的数据
易错点:要注意作用域中的值在被调用时到底等于什么?
1.2函数定义的位置
函数可以定义在全局作用域,也可以定义在局部作用域,局部作用域定义的函数可以被局部作用域和其子作用域中调用(函数嵌套)
def func():
name='wxy'
print('我是外部函数')
def inner():
print('我是内部函数')
print(name)
inner()
func()
为什么要函数嵌套?
当我们定义一个函数去实现某功能,将内部功能拆分成N个函数,担心这个N函数放在全局会与其他函数名冲突时,就可以用函数嵌套
def func():
def f1():
pass
def f2():
pass
f1()
f2()
func()
1.3函数嵌套引发的作用域问题
根据内存和执行过程分析作用域(分析函数执行过程).
作用域准则:
- 优先在自己作用域找,没有去上级作用域找
- 在作用域寻找值时,要确认此次的值为多少
- 根据函数执行过程,确认函数作用域(函数嵌套)
2.闭包
闭包,将数据封装在一个包(区域)中,使用时再去取(本质上闭包是函数嵌套的特殊嵌套)
应用场景
- 封装数据,防止污染全局
def func():
#数据定义在函数内部
name='wxy'
def f1():
pass
def f2():
pass
f1()
f2()
func()
- 封装到一个包里面,使用时取
#调用func函数会在函数作用域中定义变量a,在调用函数inner,同局作用域就会找到变量a
def func(a):
def inner():
print(a)
return inner
v1=func(1)
v2=func(2)
v1()
v2()
应用场景,基于多线程去下载视频
3.装饰器
不修改原函数的条件下,实现在函数执行前和执行后分别输出’before’ 和 ‘after’
def func():
print("我是func函数")
value = (11, 22, 33, 44)
return value
result=func()
print(result)
装饰器推导过程
- 过程1,添加函数嵌套
def func():
print("我是func函数")
value = (11, 22, 33, 44)
return value
def outer(origin):
def inner():
print('before')
#调用传入的函数
res=origin()
print('after')
return res
return inner
#func=outer(func)=inner
func=outer(func)
#func()=inner()
func()
- 过程2,添加@函数名
def outer(origin):
def inner():
print('before')
#调用传入的函数
res=origin()
print('after')
return res
return inner
# func=outer(func)
#Python中支持特殊语法,在某个函数上方使用@函数名(@outer),内部会自动执行@outer(func),执行完毕将返回值(inner)赋值给func
@outer
def func():
print("我是func函数")
value = (11, 22, 33, 44)
return value
#func()==inner()
func()
- 过程3添加参数
#传参
def outer(origin):
def inner(*args,**kwargs):
print('before')
#调用传入的函数
res=origin(*args,**kwargs)
print('after')
return res
return inner
# func=outer(func)
@outer
def func(a1):
print("我是func函数")
value = (11, 22, 33, 44)
return value
func(1)
- 执行原函数
import functools
def outer(origin):
@functools.wraps(origin)
def inner(*args,**kwargs):
print('before')
#调用传入的函数
res=origin(*args,**kwargs)
print('after')
return res
return inner
# func=outer(func)
@outer
def func(a1):
print("我是func函数")
value = (11, 22, 33, 44)
return value
func(1)
print(func.__name__) #获取函数名称
print(func.__doc__) #获取函数注释文本
补充:functools
装饰器实际上就是将原函数更改为其他函数,然后再此函数中再去调用原函数,要执行原函数,要用functools;
不用functools也可以实现装饰器的基本功能,后期项目开发,不加会报错,所以要规范写法
import functools
def outer(origin):
@functools.wraps(origin)
def inner(*args,**kwargs):
print('before')
#调用传入的函数
res=origin(*args,**kwargs)
print('after')
return res
return inner
# func=outer(func)
@outer
def func(a1):
print("我是func函数")
value = (11, 22, 33, 44)
return value
func(1)
print(func.__name__)
print(func.__doc__)
总结:装饰器,在不修改原函数内容的前提下,通过@函数可以实现在函数前后自定义执行一些功能(大量操作使用)
装饰器
- 实现原理:基于@语法和函数闭包,将原函数封装在闭包中,然后将内部函数赋值为一个新的函数(内层函数),执行函数时(就会执行内层函数)再在内层函数中执行闭包中的原函数
- 实现效果:可以在不改变原函数内部代码和调用方式的前提下,实现在函数执行和执行扩展功能
- 适用场景:多个函数统一在执行前后执行自定义的相同功能
import functools
def outer(origin):
@functools.wraps(origin)
def inner(*args,**kwargs):
#执行前
res=origin()
#执行后
return res
return inner
@outer
def func():
pass
func()
应用场景,编写网站时,有很多个页面都需要登录才能访问,可基于装饰器验证用户
4.匿名函数
匿名函数,基于lambda表达式实现定义一个可以没有名字的函数
data=lambda x:x+100
data(10) #110
lambda定义的函数格式:lambda 参数:函数体
-
参数,支持任意参数
lambda x:函数体 lambda a1,a2:函数体 lambda *args,**kwargs:函数体
-
函数体,只支持单行代码
lambda x:x+100
-
返回值,默认将函数体单行代码执行的结果返回给函数的执行者
data=lambda x:x+100 data(10) #110
匿名函数只用于简单的业务处理,可以快速创建简单函数
编写匿名函数时,由于函数体只能写一行,所以匿名函数只用于简单的业务处理
扩展功能
简单条件语句,可以基于三元表达式实现
结果=条件成立时 if 条件 else 条件不成立时
num=input('请输入数字')
data='大了' if int(num)>6 else '小了'
print(data)
匿名函数和三元表达式结合使用
data=lambda x:'大了' if x>6 else '小了'
print(data(1))
5.生成器
生成器是由函数+yield关键字创造出来的写法,在特定情况下,可以节省内存
-
生成器函数,在函数中存在yield,这个函数就是生成器函数
def func(): print(1) yield 1 print(2) yield 2
-
生成器对象,执行生成器函数时,会返回一个生成器对象
def func(): print(1) yield 1 print(2) yield 2 print(3) data=func()
注意:执行生成器函数时,函数内部代码不会执行
def func(): print(1) yield 1 #像return,执行到这个位置,不会执行 print(2) yield 2 print(3) yield 3 print(4) #最后通过next(data)会报错,StopIteration data=func() # next(data) # next(data) # next(data) #for循环执行生成器对象,不会报错 for i in data: print(i)
应用场景
-
数据量大,无法存储,要多少取多少,例:生成300w个随机4位数,并打印
import random def get_random_num(max_count): counter=0 while counter<max_count: #获取4位随机验证码 yield random.randint(1000,9999) counter+=1 data_list=get_random_num(3000000) #使用几个取几个
扩展
def func():
print(111)
v1=yield 1 #v1接收字下一次传入的值
print(v1)
print(222)
v2=yield 2
print(v2)
print(333)
v3=yield 3
print(v3) #最后通过next(data)会报错,StopIteration
print(444)
data=func()
#第一个必须传入None,n1接收yeild返回的值
n1=data.send(None)
print(n1)
n2=data.send(1000)
print(n2)
n3 = data.send(777)
print(n3)
#没有人接收了,报错StopIteration
n4 = data.send(888)
print(n4)
6.内置函数
- abs,取绝对值
abs(-1) 1
- pow,指数
pow(2,5) 2**5
- sum,求和
sum([1,2,3]) 6
- divmod,求商和余数
s1,s2=divmod(9,2) 4,1
- round,小数点后n位(四舍五入)
round(3.1415926,3) 3.142
- min,最小值
min([1,2,3,-1,-100,123]) -100
- max,最大值
max([1,2,3,-1,-100,123]) 123
- all,是否全为True
all([1,2,False]) False
- any,是否存在True
any([1,2,False]) True
- bin,十进制转二进制
- oct,十进制转八进制
- hex,十进制转十六进制
- ord,获取unicode码点(十进制)
v1=ord('王')
print(v1,hex(v1)) 29579 0x738b
- chr,根据码点(十进制)获取对应字符
v1=chr(29579)
print(v1) 王
- int
- float
- str,unicode编码
- bytes,utf-8,gbk编码
- bool
- list
- dict
- tuple
- set
- len,求长
- print,打印
- input,输入
- open,打开文件
- type,判断数据类型
- range,生成数字
- enumerate,循环,有索引
- id,求内存地址
- hash,判断是否可哈希
- help,查看帮助文档
- zip
v1=[1,2,3]
v2=[11,22,33,44]
v3=[111,222,333,444,555]
#取最短的,生成一个元组
for item in zip(v1,v2,v3):
print(item,type(item))
(1, 11, 111) <class 'tuple'>
(2, 22, 222) <class 'tuple'>
(3, 33, 333) <class 'tuple'>
- callable,是否可执行,加()可以执行
- sorted,排序,多种数据类型都可排序,sort只可以排序列表
info = {
"wupeiqi": {
'id': 10,
'age': 119
},
"root": {
'id': 20,
'age': 29
},
"seven": {
'id': 9,
'age': 9
},
"admin": {
'id': 11,
'age': 139
},
}
result=sorted(info.items(),key=lambda x:x[1]['id'])
print(result)
data_list = [
'1-5 编译器和解释器.mp4',
'1-17 今日作业.mp4',
'1-9 Python解释器种类.mp4',
'1-16 今日总结.mp4',
'1-2 课堂笔记的创建.mp4',
'1-15 Pycharm使用和破解(win系统).mp4',
'1-12 python解释器的安装(mac系统).mp4',
'1-13 python解释器的安装(win系统).mp4',
'1-8 Python介绍.mp4', '1-7 编程语言的分类.mp4',
'1-3 常见计算机基本概念.mp4',
'1-14 Pycharm使用和破解(mac系统).mp4',
'1-10 CPython解释器版本.mp4',
'1-1 今日概要.mp4',
'1-6 学习编程本质上的三件事.mp4',
'1-18 作业答案和讲解.mp4',
'1-4 编程语言.mp4',
'1-11 环境搭建说明.mp4'
]
#排序
result=sorted(data_list,key=lambda x:int(x.split(' ')[0].split('-')[-1]))
print(result)
7.推导式
推导式可以通过一行代码实现创建list,dict,tuple,set,并同时初始化一些值
-
列表
#生成列表 data_list=[ i for i in range(10)] print(data_list) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] #生成列表套列表 data_list=[ [i,i+1] for i in range(5)] print(data_list) [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]] #生成列表,做条件判断 data_list=[ i for i in range(10) if i>3] print(data_list) [4, 5, 6, 7, 8, 9]
-
集合
#生成集合 data={i for i in range(10)} print(data) # {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} #生成集合套元组 data={(i,i+1) for i in range(5)} print(data) # {(0, 1), (1, 2), (3, 4), (2, 3), (4, 5)} #生成集合,做条件判断 data={ i for i in range(10) if i>3} print(data) # {4, 5, 6, 7, 8, 9}
-
字典
#生成字典 data={i:i for i in range(4)} print(data) # {0: 0, 1: 1, 2: 2, 3: 3} #生成字典 data={i:(i,i+1) for i in range(3)} print(data) # {0: (0, 1), 1: (1, 2), 2: (2, 3)} #生成字典,做条件判断 data={ i:i for i in range(6) if i>3} print(data) # {4: 4, 5: 5}
-
元组,不同于其他类型
#生成元组 data=(i for i in range(4)) print(data) # <generator object <genexpr> at 0x00000218A9AABB30> for i in data: print(i) 0 1 2 3
推导式小高级
-
推导式支持嵌套
data = [ (i,j) for j in range(5) for i in range(10)]
https://www.luffycity.com/