返回顶部
首页 > 资讯 > 后端开发 > Python >Python 函数装饰器怎么用
  • 875
分享到

Python 函数装饰器怎么用

2023-06-21 22:06:28 875人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

这篇文章主要介绍python 函数装饰器怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、什么是函数装饰器函数装饰器是Python提供的一种增强函数功能的标记函数;装饰器是可调用的函数对象,其参数是另

这篇文章主要介绍python 函数装饰器怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

一、什么是函数装饰器

函数装饰器是Python提供的一种增强函数功能的标记函数;

装饰器是可调用的函数对象,其参数是另一个函数(被装饰的函数);

我们可以使用修饰器来封装某个函数,从而让程序在执行这个函数之前与执行完这个函数之后,分别运行某些代码。这意味着,调用者传给函数的参数值、函数返回给调用者的值,以及函数抛出的异常,都可以由修饰器访问并修改。这是个很有用的机制,能够确保用户以正确的方式使用函数,也能够用来调试程序或实现函数注册功能,此外还有许多用途。

二、函数装饰器的执行时机

函数装饰器在被装饰函数编译解析之后直接执行,装饰器是按照从上到下执行的;

函数装饰器内部定义的返回函数依附在装饰器的执行环境中;

函数装饰器每次执行都会生成新的返回函数;

import sysdef dec1(m):    print(f'{sys._getframe().f_code.co_name} is execute, arg {m.__name__}')    def newm1():        print(f'{sys._getframe().f_code.co_name}')    return newm1;@dec1def m1():    print(f'{sys._getframe().f_code.co_name}')@dec1def m11():    print(f'{sys._getframe().f_code.co_name}')if __name__ == '__main__':    print(m1)    print(m11)    print(f'm1==m11:{m1==m11}')    # dec1 is execute, arg m1# dec1 is execute, arg m11# <function dec1.<locals>.newm1 at 0x7fdfa97d9160># <function dec1.<locals>.newm1 at 0x7fdfa97d91f0># m1==m11:False

三、变量作用域

Python中将变量声明和赋值操作合一,很容易导致函数局部变量覆盖函数外的变量

b=6def f():    print(b)f()# 6
b=6def f():    print(b)    b = 9f()# UnboundLocalError: local variable 'b' referenced before assignment

通过生成的字节码可以看到两者对变量b的处理的差异,前者直接LOAD_GLOBAL,后者是LOAD_FAST,但是给b赋值却在print之后导致报错;

from dis import disb=6def f():    print(b)    # b = 9dis(f) # 5           0 LOAD_GLOBAL              0 (print) #              2 LOAD_GLOBAL              1 (b) #              4 CALL_FUNCTION            1 #              6 POP_TOP #              8 LOAD_CONST               0 (None) #             10 RETURN_VALUE
from dis import disb=6def f():    print(b)    b = 9    #  5          0 LOAD_GLOBAL              0 (print)#             2 LOAD_FAST                0 (b)#             4 CALL_FUNCTION            1#             6 POP_TOP#  6          8 LOAD_CONST               1 (9)#             10 STORE_FAST               0 (b)#             12 LOAD_CONST               0 (None)#             14 RETURN_VALUE

可以使用global来强制声明b是全局变量,然后就可以重新赋值了;

b=6def f():    global b    print(b)    b = 9f()# 6

四、闭包

闭包是是指可以访问非在函数体内定义的非全局变量的函数;

通过函数的__code__及__closure__可以看到局部变量和自由变量及闭包的情况;

def makesum():    sum = [0]    def s(val):        sum[0] += val        return sum[0]    return ss = makesum()print(s(1))print(s(2))print(s.__code__.co_varnames)print(s.__code__.co_freevars)print(s.__closure__)print(s.__closure__[0].cell_contents)# 1# 3# ('val',)# ('sum',)# (<cell at 0x7f63321f1b20: list object at 0x7f63321e8a00>,)# [3]

基于三中Python变量作用域的缘故,上边的sum只能使用列表对象,python提供的nonlocal关键字可以直接使用int类型的变量;

def makesum():    sum = 0    def s(val):        nonlocal sum        sum += val        return sum    return ss = makesum()print(s(1))print(s(2))print(s.__code__.co_varnames)print(s.__code__.co_freevars)print(s.__closure__)print(s.__closure__[0].cell_contents)# 1# 3# ('val',)# ('sum',)# (<cell at 0x7f73e6a4ab20: int object at 0x7f73e6b47970>,)# 3

五、保留函数的元数据

函数装饰器默认会使用返回的函数完全取代被装饰的函数,这样可能会导致序列化或者开发工具智能提示的问题;可以使用functools.wraps来保留原始函数的标准属性(name、module、__annotations__等);

import functoolsdef dec(func):    def real():        '''this is real function'''        pass    return realdef wrapsdec(func):    @functools.wraps(func)    def real():        '''this is real function'''        pass    return real@decdef max(nums):    '''this is max function'''    pass@wrapsdecdef sum(nums):    '''this is sum function'''print(max)print(max.__name__)print(max.__doc__)print(help(max))print()print(sum)print(sum.__name__)print(sum.__doc__)print(help(sum))# <function dec.<locals>.real at 0x7f1bfd4241f0># real# this is real function# Help on function real in module __main__:# # real()#     this is real function# # None# # <function sum at 0x7f1bfd424280># sum# this is sum function# Help on function sum in module __main__:# # sum(nums)#     this is sum function# # None

六、支持关键字参数、位置参数

def dec(func):    def real(*args, **kwargs):        result = func(*args, **kwargs)        return result    return real@decdef sum(*nums, **kwargs):    s = 0    for n in nums:        s = s + n    for a in kwargs.values():        s = s + a    return sprint(sum(1,2,3,first=1))

七、使用lru_cache缓存函数执行结果

lru_cache内部使用函数的参数作为key,使用dict进行缓存执行结果,减少重复计算;

默认支持缓存128条记录,超过后采用LRU方式丢弃多余记录;

需要注意执行中不要改变参数,否则会影响字典key的有效性;

from functools import lru_cache@lru_cache()def fibonacci(n):    print(f'fibonacci({n})')    if n<2:        return n    return fibonacci(n-1) + fibonacci(n-2)print(fibonacci(6))# fibonacci(6)# fibonacci(5)# fibonacci(4)# fibonacci(3)# fibonacci(2)# fibonacci(1)# fibonacci(0)# 8

八、使用singledispatch实现泛型函数

python不支持方法或者函数的重载,我们无法单独定义不同参数类型的同名函数;

singledispatch提供了这样一种能力,其通过注册具体的参数类型和关联的函数;

我们可以在自己的模块定义自己的类型,并实现自己的自定义函数;

import mathimport numbersfrom functools import singledispatch@singledispatchdef absall(obj):    return abs(obj)@absall.reGISter(numbers.Number)def numabs(num):    return abs(num)@absall.register(numbers.Complex)def cabs(c):    return math.sqrt(c.real*c.real + c.imag* c.imag)class Line:    def __init__(self, startx, starty, endx, endy):        self.startx = startx        self.starty = starty        self.endx = endx        self.endy = endy@absall.register(Line)def lineabs(line):    y =line.endy - line.starty    x = line.endx - line.startx    return math.sqrt(x*x + y*y)print(absall(-1.1))print(absall(3+4j))l = Line(1,2,4,6)print(absall(l))# 1.1# 5.0# 5.0

九、通过参数控制函数装饰器的行为

函数装饰器本身不支持传递参数,解析源代码的时候,python会将被装饰的函数对象作为第一个参数传递给装饰器;

我们可以通过在函数装饰器外再嵌套一个函数工厂来承载装饰特定函数的时候设置的参数; 

def accesscontrol(checkuser=True, updatesession=True):    def dec(func):        def checkuserf():            print('check user')            return True        def updatesessionf():            print('update session')            return True        def access():            if checkuser:                checkuserf()            if updatesession:               updatesessionf()            func()        return access    return dec@accesscontrol()def pushitem():    print('pushitem')    return True@accesscontrol(checkuser=False)def getitem():    print('getitem')    return True# pushitem()# print()# getitem()# # check user# update session# pushitem# # update session# getitem

以上是“Python 函数装饰器怎么用”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网Python频道!

--结束END--

本文标题: Python 函数装饰器怎么用

本文链接: https://lsjlt.com/news/301091.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python中怎么使用装饰器装饰函数
    这篇文章将为大家详细讲解有关Python中怎么使用装饰器装饰函数,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。***个函数deco是装饰函数,它的参数就是被装饰的函数对象。我们可以在deco...
    99+
    2023-06-17
  • Python 函数装饰器怎么用
    这篇文章主要介绍Python 函数装饰器怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、什么是函数装饰器函数装饰器是Python提供的一种增强函数功能的标记函数;装饰器是可调用的函数对象,其参数是另...
    99+
    2023-06-21
  • Python中怎么使用装饰器来装饰函数
    在Python中,装饰器是一种函数,它接受一个函数作为参数,并返回一个新的函数。通过使用装饰器,可以在不修改原始函数代码的情况下添加...
    99+
    2024-03-12
    Python
  • Python装饰器函数怎么使用
    这篇文章主要介绍了Python装饰器函数怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Python装饰器函数怎么使用文章都会有所收获,下面我们一起来看看吧。假如我写了一个函数 fdef f()...
    99+
    2023-07-02
  • 怎么在python中使用函数装饰器
    怎么在python中使用函数装饰器?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Python主要用来做什么Python主要应用于:1、Web开发;2、数据科学研...
    99+
    2023-06-14
  • python装饰器1:函数装饰器详解
    装饰器1:函数装饰器 装饰器2:类装饰器 装饰器3:进阶 先混个眼熟 谁可以作为装饰器(可以将谁编写成装饰器): 函数 方法 实现了__call__的可调用类 装饰器可以去装饰谁(谁可以被装饰): 函数 方法 类 基础...
    99+
    2023-01-30
    详解 函数 python
  • Python装饰器-闭包与函数装饰器
    一、闭包在学习装饰器前,需要先了解闭包的概念。形成闭包的要点:函数嵌套将内部函数作为外部函数的返回值内部函数必须要使用到外部函数的变量下面以一个计算列表平均值的案例来讲解闭包:def make_average(): # 创建一个列表,用来保...
    99+
    2023-05-14
    Python 函数 装饰器
  • Python函数的装饰器
    函数的装饰器. 1. 装饰器   开闭原则:         对功能的扩展开放         对代码的修改是封闭     通用装饰器语法: def wrapper(fn): def inner(*args, **kw...
    99+
    2023-01-30
    函数 Python
  • python之装饰器(函数)
    1. 装饰器   遵循的原则:     开闭原则:   对功能的扩展开放  对代码的修改是封闭 # 通用装饰器写法 # 存在的意义: 在不破坏原有函数和原有函数调用的基础上,给函数添加新的功能. def wrapper...
    99+
    2023-01-30
    函数 python
  • Python返回函数、闭包、装饰器、偏函数怎么使用
    今天小编给大家分享一下Python返回函数、闭包、装饰器、偏函数怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1.返...
    99+
    2023-07-02
  • Python 函数装饰器详解
    目录使用场景授权(Authorization)日志(Logging)带参数的装饰器在函数中嵌入装饰器装饰器类总结装饰器(Decorators)是 Python 的一个重要部分。简单地...
    99+
    2024-04-02
  • Python函数装饰器应用教程
    目录一、什么是函数装饰器二、函数装饰器的执行时机三、变量作用域四、闭包五、保留函数的元数据七、使用lru_cache缓存函数执行结果八、使用singledispatch实现泛型函数九...
    99+
    2024-04-02
  • Python函数装饰器的使用教程
    目录典型的函数装饰器叠放装饰器参数化装饰器标准库中的装饰器functools.wrapsfunctools.lru_cachefunctools.singledispatch小结参考资料:典型的函数装饰器 以下示例...
    99+
    2022-06-02
    python 装饰器 python 函数装饰器
  • Python函数装饰器的使用详解
    目录装饰器装饰器的定义装饰器的意义装饰器的使用无参装饰器有参装饰器实例练习总结装饰器 装饰器的定义 关于装饰器的定义,我们先来看一段github上大佬的定义: Function de...
    99+
    2024-04-02
  • Python中怎么使用装饰器实现函数的缓存
    这篇文章主要介绍“Python中怎么使用装饰器实现函数的缓存”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python中怎么使用装饰器实现函数的缓存”文章能帮助大家解决问题。装饰器模式在以下场景中被...
    99+
    2023-07-05
  • 怎么用Python装饰器来缓存函数的返回值
    本篇内容主要讲解“怎么用Python装饰器来缓存函数的返回值”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用Python装饰器来缓存函数的返回值”吧!Pythonclass Memoized...
    99+
    2023-06-03
  • 如何使用Python中的装饰器函数
    如何使用Python中的装饰器函数在Python编程中,装饰器(decorators)是一种非常有用的工具。它允许我们在不修改原始函数代码的情况下,对函数进行额外的功能扩展。装饰器函数可以在函数执行前后自动执行一些操作,例如记录日志、计时、...
    99+
    2023-10-22
    Python 使用 装饰器函数
  • python3--函数的有用信息,带参数的装饰器,多个装饰器装饰同一个函数
    开放封闭原则1 对扩展是开放的    为什么要对扩展开放呢?    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改,所以我们必须允许代码扩展,添加新功能2 对修...
    99+
    2023-01-30
    函数 多个 有用
  • 浅析Python编写函数装饰器
    编写函数装饰器 本节主要介绍编写函数装饰器的相关内容。 跟踪调用 如下代码定义并应用一个函数装饰器,来统计对装饰的函数的调用次数,并且针对每一次调用打印跟踪信息。 class tracer: def ...
    99+
    2022-06-04
    函数 Python
  • 深入了解Python装饰器函数
    本篇文章给大家带来了关于python的相关知识,其中主要整理了装饰器函数的相关问题,包括了装饰器的形成过程、本质与功能、进阶与优化等等内容,下面一起来看一下,希望对大家有帮助。假如我写了一个函数 fdef f(): print(&#...
    99+
    2022-06-26
    python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作