ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python 函数与装饰器入门

Python 函数与装饰器入门 文章目录一、函数基础回顾1. 最简单的函数2. 参数的几种形式二、函数是“一等公民”三、闭包Closure四、装饰器入门1. 最简单的装饰器2. 带参数的函数如何装饰3. 保留原函数信息重要五、常见实用装饰器示例1. 计时装饰器2. 重试装饰器简化版3. 权限检查示例思想六、装饰器的执行顺序函数是 Python 中最核心的抽象工具之一装饰器则是在函数基础上发展出来的强大语法糖。掌握这两部分能让你写出更清晰、可复用、可扩展的代码。一、函数基础回顾1. 最简单的函数defgreet(name:str)-str:向某人打招呼returnfHello,{name}!print(greet(Alice))# Hello, Alice!def定义函数参数可以加类型注解推荐-后面是返回值类型注解文档字符串docstring用三引号写在函数体第一行2. 参数的几种形式defexample(a,b10,*args,c,d20,**kwargs):print(fa{a}, b{b}, args{args}, c{c}, d{d}, kwargs{kwargs})参数类型写法说明位置参数a必须按顺序传默认参数b10可省略可变位置参数*args接收多余的位置参数元组仅限关键字参数c*后面必须用关键字传递可变关键字参数**kwargs接收多余的关键字参数字典调用示例example(1,2,3,4,c5,e6,f7)# a1, b2, args(3, 4), c5, d20, kwargs{e: 6, f: 7}注意默认参数只计算一次不要用可变对象list、dict作为默认值。# 错误示范defbad_append(item,lst[]):lst.append(item)returnlst# 正确写法defgood_append(item,lstNone):iflstisNone:lst[]lst.append(item)returnlst二、函数是“一等公民”在 Python 中函数可以像普通变量一样被传递、赋值、作为参数和返回值。defadd(x,y):returnxydefsub(x,y):returnx-ydefcalculate(func,x,y):returnfunc(x,y)print(calculate(add,10,5))# 15print(calculate(sub,10,5))# 5这是装饰器和很多高级用法的基础。三、闭包Closure内部函数可以记住并访问外部函数的变量即使外部函数已经执行完毕。defmake_multiplier(n):defmultiplier(x):returnx*n# 引用了外部的 nreturnmultiplier doublemake_multiplier(2)triplemake_multiplier(3)print(double(5))# 10print(triple(5))# 15闭包常用于创建带状态的函数实现装饰器延迟计算四、装饰器入门装饰器本质上是一个接收函数作为参数、并返回一个新函数的高阶函数。它用来在不修改原函数代码的情况下增加额外功能。1. 最简单的装饰器defsimple_decorator(func):defwrapper():print(函数执行前)resultfunc()print(函数执行后)returnresultreturnwrappersimple_decorator# 语法糖defsay_hello():print(Hello!)say_hello()输出函数执行前 Hello! 函数执行后simple_decorator等价于say_hellosimple_decorator(say_hello)2. 带参数的函数如何装饰原函数有参数时wrapper也要能接收参数deflog_decorator(func):defwrapper(*args,**kwargs):# 接收任意参数print(f调用函数:{func.__name__})print(f参数: args{args}, kwargs{kwargs})resultfunc(*args,**kwargs)print(f返回值:{result})returnresultreturnwrapperlog_decoratordefadd(a,b):returnabprint(add(3,5))3. 保留原函数信息重要直接写装饰器会丢失原函数的__name__、__doc__等信息。推荐使用functools.wrapsfromfunctoolsimportwrapsdeflog_decorator(func):wraps(func)# 关键关键推荐加上defwrapper(*args,**kwargs):print(f调用:{func.__name__})returnfunc(*args,**kwargs)returnwrapper五、常见实用装饰器示例1. 计时装饰器importtimefromfunctoolsimportwrapsdeftimer(func):wraps(func)defwrapper(*args,**kwargs):starttime.perf_counter()resultfunc(*args,**kwargs)endtime.perf_counter()print(f{func.__name__}耗时:{end-start:.4f}秒)returnresultreturnwrappertimerdefslow_function():time.sleep(1)slow_function()2. 重试装饰器简化版fromfunctoolsimportwrapsimporttimedefretry(max_attempts3,delay1):defdecorator(func):wraps(func)defwrapper(*args,**kwargs):forattemptinrange(1,max_attempts1):try:returnfunc(*args,**kwargs)exceptExceptionase:print(f第{attempt}次失败:{e})ifattemptmax_attempts:raisetime.sleep(delay)returnwrapperreturndecoratorretry(max_attempts3,delay0.5)defunstable_api():# 模拟偶尔失败的操作importrandomifrandom.random()0.7:raiseConnectionError(网络错误)return成功注意这里retry是一个带参数的装饰器所以多包了一层。3. 权限检查示例思想defrequire_admin(func):wraps(func)defwrapper(user,*args,**kwargs):ifnotuser.get(is_admin):raisePermissionError(需要管理员权限)returnfunc(user,*args,**kwargs)returnwrapper六、装饰器的执行顺序多个装饰器时靠近函数的先执行从下往上应用decorator_adecorator_bdefmy_func():pass# 等价于my_funcdecorator_a(decorator_b(my_func)) 感谢阅读想了解更多 我的博客网站 | 记录思考分享干货 我的个人主页 | 关于我、开源项目
返回列表