1、匿名函数lambda的使用
函数定义中
-
def关键字,可以定义带有名称的函数
-
lambda关键字,可以定义匿名函数(无名称)
有名称的函数,可以基于名称重复使用
无名称的匿名函数,只可临时使用一次
匿名函数定义语法:
lambda 传入参数:函数体(一行代码)
-
lambda 是关键字,表示匿名函数
-
传入参数表示匿名函数的形式参数,如:x,y表示接收2个参数
-
函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码
print((lambda x:x+10)(20))
fun = lambda x:abs(x)
print(fun(-10))
funa = lambda : print('这是一个匿名函数')
funa()
fun4 = lambda x,y=1:x+y
print(fun4(4,5))
print(fun4(4))
funb = lambda *args:sum(args)
print(funb(1,2,3,4,5))
func = lambda **kwargs:kwargs
print(func(name = '张三',age = 18))
fund = lambda a,b:a if a>b else b #python的三木运算符
print(fund(1,2))
lambda函数的特性
- lambda函数是匿名的,即它是没有名字的函数,并且自带return。
- lambda函数可以使用任意数量的参数,但只能包含一个表达式。
- lambda函数返回一个值,这个值就是表达式的结果。
- lambda函数的生命周期很短,调用后立即被回收。
2、高阶函数
Python中的高阶函数:将一个或多个函数作为函数的参数
2.1 map函数
用于将一个函数应用到一个序列的每一个元素,并返回一个包含结果的迭代器。
语法:map(函数,可迭代对象)
l = (1,2,3,4,5)
ret = map(str,l)
print(ret) #<map object at 0x0000016CE0241B10>
print(list(ret)) #['1', '2', '3', '4', '5']
ls = [1,2,3,4,5]
ret = list(map(lambda x:x*5,ls))
print(ret) #[5, 10, 15, 20, 25]
2.2 reduce函数
reduce 函数用于对序列进行累计运算,它通常需要从 functools 模块中导入。
语法:from functools import reduce reduce(函数,可迭代对象)
from functools import reduce
l = [1,2,3,4,5]
ret1 = reduce(lambda x,y:x+y,l)
print(ret1) #15 x是计数器,y是游标
ret2 = reduce(lambda x,y:x+2*y,l)
print(ret2) #29 因为第一个1是被引用了
ret3 = reduce(lambda x,y:x*y,l)
print(ret3) #120
2.3 filter函数
用于遍历序列中的每个元素,根据条件进行筛选,返回一个包含被筛选后结果的迭代器。
语法:filter(函数,可迭代对象)
import random
l = [random.randint(10,100) for i in range(10)]
print(l) #[80, 44, 88, 33, 32, 42, 10, 44, 38, 93]
ret1 = list(filter(lambda x:x%2==0,l))
print(ret1) #[80, 44, 88, 32, 42, 10, 44, 38]
2.4 排序函数
ls = [['b呈',4],['c成',2],['a城',3],['e程',1],['d诚',5]]
#排序
ls.sort()
print(ls)
#按照数字排序--itemgetter--获取多维数组中某个维度的元素值
import operator
ls.sort(key = operator.itemgetter(1),reverse = True)
print(ls)
ls.sort(key = lambda x:x[0],reverse = True) #[0]表示第二维度第几位数
print(ls)#[['e程', 1], ['d诚', 5], ['c成', 2], ['b呈', 4], ['a城', 3]]
3、装饰器
3.1 装饰器的概念
在python中,装饰器本质是一个特殊的嵌套函数,它接收一个函数【被装饰的函数】做参数,并返回一个新的函数【装饰后的函数】
装饰器的最大作用:在不改变原有函数【被装饰的函数】的基础上给它添加新的功能。
3.2 装饰器的基本用法
#装饰器
def out_func(function):
def in_func():
print("欢迎",end='')
function()
print('请进')
return in_func
#被修饰函数
def func():
print("光临",end=' ')
#第一种调用方式
out_func(func)() #欢迎光临 请进
#第二种调用方式
func = out_func(func)
func() #欢迎光临 请进
3.3 装饰器语法糖
语法糖是由编程语言提供的,可以让代码更加简洁、高效、易读和易写。语法糖不改变不会带来新的功能,也不会改变编程的结果,但是使用它会更加方便。
python中有很多语法糖,已用的有:
- 列表推导式
- 集合推导式
- 字典推导式
- f-string print(f"{}")
- 解包
- 装饰器
语法:
装饰函数
@装饰函数名
def 被装饰函数名
代码块
#装饰器
def out_func(function):
def in_func():
print("欢迎",end='')
function()
print('请进')
return in_func
@out_func
#被修饰函数
def func():
print("光临",end=' ')
func() #欢迎光临 请进
3.4 被装饰函数有参数
若被装饰函数有参数,那么装饰器的内部函数也需要有参数,保证在内部调用被装饰函数的时候能正确传参。
3.4.1 被装饰函数有一个参数
#装饰器
def out_func(function):
def in_func(x):
print("欢迎",end='')
function(x)
print('请进')
return in_func
@out_func
#被修饰函数
def func(x):
print(f"光临{x}次",end=' ')
func(3) #欢迎光临3次 请进
3.4.2 被装饰函数有未知个参数
import time
# 装饰器
#判断1-10000素数两个方法需要的时间
def out_fun(function):
def in_fun(*args, **kwargs):
start = time.time()
function(*args, **kwargs)
end = time.time()
print(end - start)
return in_fun
# 被装饰函数1
@out_fun
def fun1(x):
for i in range(1,x):
for j in range(2,i):
if i%j==0:
pass
else:
pass
# 被装饰函数2
@out_fun
def fun2(x):
for i in range(1,x):
for j in range(2,int(i**0.5+1)):
if i%j==0:
pass
else:
pass
fun1(10000) #1.992875576019287
fun2(10000) #0.024277210235595703
3.5 装饰器带参数
现在装饰器要带有参数,而且装饰器的外部函数要接收被装饰函数的函数名,内部函数要接收被装饰函数的参数,那么为了保证装饰器参数、被装饰函数参数的正确传递,我们在装饰器外部函数再嵌套一层函数,用于接收装饰器参数。
#装饰器
def Func(num):
def out_func(function):
def in_func(x):
print(num,end = ' ')
print("欢迎",end='')
function(x)
print('请进')
return in_func
return out_func
@Func("您好")
#被修饰函数
def func(x):
print(f"光临{x}次",end=' ')
func(3) #您好 欢迎光临3次 请进
3.6 装饰器嵌套
已学的嵌套:列表、字符串、元组、集合、字典、函数、循环、选择
装饰器嵌套就是被装饰函数 可以 被多个装饰器装饰。
#装饰器
def out_func(function):
def in_func():
print("装饰器1开始")
function()
print('装饰1结束')
return in_func
def out_func2(function):
def in_func2():
print("装饰器2开始")
function()
print('装饰2结束')
return in_func2
@out_func
@out_func2
#被修饰函数
def func():
print('观察')
func()
'''
装饰器1开始
装饰器2开始
观察
装饰2结束
装饰1结束
'''
3.7 类装饰器
除了可以自定义一个新的函数用作装饰器之外,也可以将一个类作为装饰器,为被装饰的函数添加新的功能。类装饰器通过实现类的__call__方法,使得类的实例可以被当作函数来调用,丛而实现对其他函数的装饰。
3.8.1 记录日志
装饰器可以用来记录函数调用的详细信息,包括调用时间、参数、返回值等
import loggi
import logging
def log_decorator(func):
def wrapper(*args, **kwargs):
logging.basicConfig(filename='./app.log', level=logging.INFO, filemode='a',
format='%(name)s - %(levelname)s - %(asctime)s - %(message)s')
logging.warning(f"calling function:{func.__name__} with args:{args} and "
f"kwargs:{kwargs}")
ret = func(*args, **kwargs)
logging.warning(f"function {func.__name__} returned: {ret}")
return ret
return wrapper
@log_decorator
def test():
print('123')
test()
3.8.2 性能检测
装饰器可以用来测量函数执行所需的时间,帮助识别性能瓶颈。
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
ret = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} took {(end_time - start_time):.10f} seconds to run")
return ret
return wrapper
@timer
def process_list(my_list):
for i in my_list:
pass
my_list = list(range(10000))
process_list(my_list)
3.8.3 权限验证
装饰器可以用来检查用户是否有权限执行特定的函数或方法。
class User:
def __init__(self, username, role):
self.username = username
self.role = role
# 装饰器:检查用户是否具有管理员权限
def admin_only(func):
def wrapper(user, *args, **kwargs):
if user.role != 'admin':
raise PermissionError(f"User {user.username} is not "
f"authorized to perform this action")
return func(user, *args, **kwargs)
return wrapper
@admin_only
def delete_user(user, user_to_delete):
"""只有管理员可以删除用户"""
print(f'User {user_to_delete.username} has been deleted by {user.username}')
# 测试代码
admin_user = User('Alice', 'admin')
normal_user = User('Bob', 'user')
# 尝试以管理员身份删除用户
delete_user(admin_user, normal_user)
# 尝试以普通用户身份删除用户
delete_user(normal_user, admin_user)