
每天1分钟,轻松懂 Python
这是一份有基础、有深度的 Python 核心技术手册
函数与闭包
1、函数是一等公民
Python 中函数可以赋值给变量;可以作为参数传递;也可以在函数里定义函数。
示例:将函数作为参数传递
python
def func(message):
print(f"Got message: {message}")
send_message = func # 函数赋值给变量
send_message("hello world") # 这里调用:Got message: hello world
2、函数嵌套与闭包
在函数内定义子函数,最后,返回子函数。在子函数可以访问外层函数变量。
python
def outer():
x = 1
def inner():
print(x) # 访问 outer 的变量 x
return inner
fn = outer()
fn() # 输出 1(闭包保留外层变量引用 )
核心语法
1、简单的装饰器
装饰器是用于 "包装函数",在不修改原函数的前提下,添加额外逻辑(如日志、权限校验 )。
python
def my_decorator(func):
def wrapper():
print("wrapper of decorator")
func()
return wrapper
@my_decorator # 语法等价于 greet = my_decorator(greet)
def greet():
print("hello world")
greet()
# 输出:
# wrapper of decorator
# hello world
2、带参数的装饰器
*args、**kwargs 可以接收任意数量和类型的参数。
python
def my_decorator(func):
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper
@my_decorator
def greet(name, message):
print(f"Hi {name}, {message}")
greet("Mr.Wang", "Good to see you.")
# 输出
# wrapper of decorator
# Hi Mr.Wang, Good to see you.
保留函数原信息
被装饰后函数,会默认丢失原信息(如 __name__ ),需要用 functools.wraps 修复:
python
import functools
def my_decorator(func):
@functools.wraps(func) # 保留原函数信息 <<<<<<<<
def wrapper(*args, **kwargs):
print("wrapper of decorator")
func(*args, **kwargs)
return wrapper
@my_decorator
def greet():
print("hello world")
print(greet.__name__) # 输出 'greet'(否则为 'wrapper' )
类装饰器 和 多层装饰器
1、类装饰器
用类实现装饰器,通过 __call__ 方法拦截函数调用:
python
class CountCalls:
def __init__(self, func):
self.func = func
self.num_calls = 0
def __call__(self, *args, **kwargs):
self.num_calls += 1
print(f"Call {self.num_calls} of {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def greet(name):
print(f"Hi {name}")
greet("Mr.Wang")
# 输出:
# Call 1 of greet
# Hi Mr.Wang
greet("Mr.Li")
# 输出:
# Call 2 of greet
# Hi Mr.Li
2、多层装饰器
多个装饰器叠加,执行顺序为从外到内包裹,从内到外执行:
python
@decorator1
@decorator2
def greet():
print("hello world")
# 执行逻辑等价于 greet = decorator1(decorator2(greet))
# 执行时:decorator1 的 wrapper → decorator2 的 wrapper → 原函数
使用场景
1、身份认证
校验用户登录状态,未登录则拦截操作:
python
import functools
def authenticate(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if not check_login_state(): # 自定义校验逻辑
raise Exception("Authentication failed")
return func(*args, **kwargs)
return wrapper
@authenticate
def post_comment(content):
print(f"发布评论:{content}")
2、日志记录
统计函数执行时间、打印调用日志:
python
import time
import functools
def log_execution_time(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 执行耗时:{end - start} 秒") # 记录耗时
return result
return wrapper
@log_execution_time
def train_model():
time.sleep(2) # 模拟耗时操作
3、输入合法性检查
预处理函数参数,确保符合规则:
python
import functools
def validate_params(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
# 示例:校验第一个参数为数字
if not isinstance(args[0], (int, float)):
raise ValueError("参数必须为数字")
return func(*args, **kwargs)
return wrapper
@validate_params
def process_data(data):
print(f"处理数据:{data}")
4、缓存优化
@lru_cache 会缓存函数参数和结果,避免重复计算(如 functools.lru_cache ):
python
import functools
@functools.lru_cache(maxsize=128)
def cal(n):
print(f"开始执行 cal. 参数:{n}")
time.sleep(3)
return n * 2
cal(100)
cal(100)
cal(100)
# 重复调用 cal(100) 时,只输出一个 "开始执行 cal. 参数:100"
-------- 写在最后 --------
关注我,每天1分钟,轻松懂 Python
我的同名公众号正在连载《FastAPI 开发实战》、《Python 核心技术》、《职场》。
点赞 :如果觉得有收获,点赞支持一下吧!
分享 :分享给身边同样对Python感兴趣的朋友!
关注我 :不要错过每一篇 Python 实战内容!
#Python #FastAPI #API #Web开发 #程序员 #编程教程 #效率提升 #装饰器