Python基础(十四)—装饰器 wrapper

LilyGO T-Watch学习(一)环境搭建,编译下载 1、安装arduino IDE, 安装后按照说明添加lib IDE上选择“项目->加载库->添加.ZIP库”,选择C:\Users\用户名\Documents\Arduino\libraries\下的TTGO_TWatch_Library-master.zip; 查看是否添加成功: 项目->加载库,滑到最后可看见已添加的TTGO... 参考:https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library 2、安装esp32 ardui 阅读详情
AI摘要

本文围绕Python装饰器展开,介绍了装饰器的作用,即给已有函数或对象添加额外功能。阐述了无参数、可变参数装饰器,高阶装饰器(带参数、基于类实现、带参数的类装饰器),还提及内置装饰器 @property。同时说明了装饰器的注意事项,如代码执行顺序、functools.wraps 的使用等。

装饰器 wrapper

先上一篇博文:详解Python装饰器

  • 装饰器的作用
    装饰器的作用就是为已经存在的函数或对象添加额外的功能。

    装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

  • 无参数的装饰器
def debug(func):
    def wrapper():
        print('[DEBUG]: enter {}()'.format(func.__name__))
        return func()
    return wrapper

@debug
def say_hello():
    print('hello!')
say_hello()
"""
[DEBUG]: enter say_hello()
hello!
"""

将 @debug 放在say_hello() 前面,相当于执行了
say_hello = debug(say_hello)
由于debug()是一个装饰器,返回了wrapper函数,所以原来的say_hello()依然存在,只是现在同名的now变量指向了新的函数,于是调用say_hello()将执行新的函数,即在debug()函数中返回的wrapper()函数。

  • 可变参数的装饰器
def debug(func):
    def wrapper(*args, **kwargs):
        print('[DEBUG]: enter {}()'.format(func.__name__))
        return func(*args, **kwargs)
    return wrapper

@debug
def say_hello(name, something):
    print('hello!{}{}'.format(name, something))

say_hello('luozheng', '.')
"""
[DEBUG]: enter say_hello()
hello!luozheng.
"""

Python提供了可变参数*args和关键字参数**kwargs,有了这两个参数,装饰器就可以用于任意目标函数。

高阶装饰器

  • 带参数的装饰器
    假设前文的装饰器需要完成的功能不仅仅是能在进入某个函数后打出log信息,而且还需指定log的级别,那么装饰器就会是这样的。
def logging(level):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            print('[{level}]: enter function {func}()'.format(
                level=level,
                func=func.__name__))
            return func(*args, **kwargs)
        return inner_wrapper
    return wrapper

@logging(level='INFO')
def say(something):
    print('say {}!'.format(something))

# 如果没有使用@语法,等同于
# say = logging(level='INFO')(say)
@logging(level='DEBUG')
def do(something):
    print('do {}...'.format(something))

if __name__ == '__main__':
    say('hello')
    do('my work')

"""
[INFO]: enter function say()
say hello!
[DEBUG]: enter function do()
do my work...
"""

当带参数的装饰器被打在某个函数上时,比如@logging(level=‘DEBUG’),它其实是一个函数,会马上被执行,只要这个它返回的结果是一个装饰器时,那就没问题。细细再体会一下。

  • 基于类实现的装饰器
    装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重载了__call__()方法,那么这个对象就是callable的。重载__call__些魔法方法一般会改变对象的内部行为,让一个类对象拥有了被调用的行为。
class Test():
    def __call__(self):
        print 'call me!'

t = Test()
t()  # call me

装饰器要求接受一个callable对象,并返回一个callable对象(不太严谨,详见后文)。那么用类来实现也是也可以的。我们可以让类的构造函数__init__()接受一个函数,然后重载__call__()并返回一个函数,也可以达到装饰器函数的效果。

class logging(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print('[DEBUG]: enter function {func}()'.format(
            func=self.func.__name__))
        return self.func(*args, **kwargs)
@logging
def say(something):
    print('say {}'.format(something))

say('love you.')
"""
[DEBUG]: enter function say()
say love you.
"""
  • 带参数的类装饰器
class logging(object):
    def __init__(self, level='INFO'):
        self.level = level

    def __call__(self, func):  # 接受函数
        def wrapper(*args, **kwargs):
            print('[{level}]: enter function {func}()'.format(
                level=self.level,
                func=func.__name__))
            func(*args, **kwargs)

        return wrapper  # 返回函数

@logging(level='INFO')
def say(something):
    print('say {}'.format(something))

say('love you.')
print(say.__name__)  # wrapper
  • 内置装饰器 @property
    进行类属性读写的限制,Python基础(十二)—面向对象拾遗(slots、@property、枚举类、元类)有讲解到。

装饰器的注意事项

  • 不确定的代码执行顺序
    最好不要在装饰器函数之外添加逻辑功能,否则这个装饰器就不受你控制了。
def html_tags(tag_name):
    print('begin outer function.')
    def wrapper_(func):
        print('begin of inner wrapper function.')
        def wrapper(*args, **kwargs):
            content = func(*args, **kwargs)
            print('<{tag}>{content}</{tag}>'.format(tag=tag_name, content=content))
        print('end of inner wrapper function.')
        return wrapper
    print('end of outer function')
    return wrapper_

@html_tags('b')
def hello(name='Toby'):
    return 'Hello {}!'.format(name)

hello()
hello()
"""
begin outer function.
end of outer function
begin of inner wrapper function.
end of inner wrapper function.
<b>Hello Toby!</b>
<b>Hello Toby!</b>
"""
  • functools.wraps
    上面的一个例子:
    print(say._name_) # wrapper
    这是因为@等同于这样的写法:
    say = logging(say)
    logging其实返回的函数名字刚好是wrapper,那么上面的这个语句刚好就是把这个结果赋值给say,say的__name__自然也就是wrapper了,不仅仅是name,其他属性也都是来自wrapper,比如doc,source等等。
    使用标准库里的functools.wraps,可以基本解决这个问题。
from functools import wraps
import datetime

def logging(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """print log before a function."""
        print('[DEBUG] {}: enter {}()'.format(datetime.now(), func.__name__))
        return func(*args, **kwargs)
    return wrapper

@logging
def say(something):
    """say something"""
    print('say {}!'.format(something))

print(say.__name__)  # say
print(say.__doc__) # say something
def one(func):
    print('----1----')
    def two():
        print('----2----')
        func()
    return two

def a(func):
    print('----a----')
    def b():
        print('----b----')
        func()
    return b

@one
@a
def demo():
    print('----3----')

demo()
"""
----a----
----1----
----2----
----b----
----3----
"""

个人博客:Loak 正 - 关注人工智能及互联网的个人博客
文章地址:Python基础(十四)—装饰器 wrapper

Eclipse 打开报 `An error has occurred. See the log null` 错误及解决方法 摘要:Eclipse启动时报错"An error has occurred. See the log null"通常是由于非正常关闭导致org.eclipse.osgi配置文件损坏所致。解决方法包括:1)以管理员身份启动(适用于权限问题);2)删除损坏的org.eclipse.osgi文件夹;3)最有效的方法是换目录重新安装Eclipse。建议规范使用开发工具、及时备份项目,避免非正常关闭操作,以维护稳定的开发环境。该问题虽小但提醒我们开发工具的日常维护同样重要。 阅读详情

相关推荐

Nvidia AGX Xavier刷机指北

因为工作的关系,要在AGX上安装CUDA。nvidia官网上没找到适合AGX版本的CUDA,只能走刷机的路子。刷机过程中,也遇到一些坑,做个记录。 需要有一台ubuntu系统的电脑作为主机Host。我的主机系统为Ubuntu18.04 整个刷机过程为: 在Host上安装sdkmanager,整个刷机过程主要通过sdkmanager来操作。 在Host自动下载一些系统组件,各种deb包 Host上制作OS系统镜像,烧录到AGX中 Host上之前下载好的deb包,安装到AGX中。 完结,撒花 ...

sinat_38685124的博客 6296

Python-装饰器(wrapper)

一.装饰器 1.什么是装饰器 python装饰器用于拓展原来函数功能的一种函数,这个函数的返回值也是一个函数。 2.不带参数的简单装饰器 import time print(time.time()) # 获取当前时间 time.sleep(10) #让程序在执行到这个位置的时候停一会儿 def timmer(f): #装饰器函数 def inner(): start = time.time() ret = f() .

Could_tzw的博客 5244

分享通达信破解交易接口的使用!

那其实通达信破解交易接口的使用方法比较复杂,这里以MA均线指标为例子,只要理解了这些操作步骤,就可以很容易地使用其他指标包括自己编写的指标来进行交易。委托结果(包含委托编号), 需要分配 1024*1024 字节的空间。委托结果数组, 每项结果需要分配 1024*1024 字节的空间。0: 买入, 1: 卖出, 2: 融资买入, 3: 融券卖出,4: (市价委托)上海五档即成剩撤, 深圳五档即成剩撤。4: 买券还券, 5: 卖券还款, 6: 现券还券。0: 上海限价委托, 深圳限价委托。

1841085904的博客 2361

一文教你搞懂python函数装饰器(wrapper)

python函数装饰器 函数装饰器,定义一个装饰器后,调用改装饰器,个人理解是在目标函数前后做一些操作。 例如:定义一个鉴权的函数装饰器,在给目标函数的时候添加装饰函数就可以做到先鉴权,鉴权成功再运行目标函数 装饰器模板参考如下: #模板 # 装饰器:wrapper # 模板: # def 装饰器名(func): #def 与 @之后的函数名称一致 调用函数func与ret=func(*args,**kwargs)内部函数一致 # def wrappe

python真的好用,不信你试试 1万+

利用RFIDIOt和NFC进行Hitag2密码暴力破解: Python代码实现

RFID即无线射频识别,是一种通信技术,可以通过无线电信号读取、捕获和保存终端上的信息。这项技术在物流、零售、医疗等领域有着广泛的应用。NFC即近场通信,是一种短距离的高频无线通信技术,允许电子设备之间进行非接触式点对点数据传输。Hitag2是一种常见的RFID标签,广泛应用于汽车防盗系统、门禁系统等。由于其安全性在过去被广泛认可,很多设备都采用了这种标签。但近年来随着密码破解技术的发展,Hitag2的安全性受到了一些挑战。

qq_38334677的博客 1563

基于STM32、HAL库的TCA9555PWR I/O扩展器驱动程序设计

define TCA9555_ADDR_BASE 0x20 // 基础地址 (A0=A1=A2=0)* @param direction: 方向 (0=输出, 1=输入)* @param direction: 方向 (0=输出, 1=输入)* @param polarity: 极性 (0=正常, 1=反转)* @param polarity: 极性 (0=正常, 1=反转)

corlin6688的博客 528

python装饰器

1.概念

自定义的博客 343

PyQt(Python+Qt)学习随笔:PyQt界面派生类构造方法中super方法的使用

老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在《第15.7节 PyQt入门学习:PyQt5应用构建详细过程介绍》和订阅专栏《第二章、PyQt5应用构建详细过程介绍》中,老猿介绍界面派生类的构造方法如下: class MediaPlayerWin(QtWidgets.QWidget,Ui_UI_PlayerWin): def __i...

老猿Python 2711

Python装饰器学习

python装饰器

倔强不倒翁的博客 1514

CloudCompare 多窗口联动显示点云

CloudCompare支持多窗口联动显示多个点云数据,可以用来比对原始点云数据与语义分割后的结果。 一、创建多个视窗 打开CloudCompare后会默认有一个视图,我们要同时打开两个数据就需要再创建一个视图,选择菜单栏里的3D Views,在下拉菜单中点击new,这样就创建了一个新的视图,这时3D Views的下拉菜单中有3D View 1和3D View 2两个视图,然后点击3D Views下拉菜单中的Title,这时在数据展示区就会出现两个并列的窗口。 二、分别加载点云数据 将数据分别拖进两个

zhaoguanhua的博客 2740

YOLO26改进策略【Neck】| 关键点检测:SDFM 表层细节融合模块,利用通道-空间注意力机制,实现深层与浅层特征融合,抑制噪声干扰

本文记录的是利用SDFM 模块改进 YOLO26 的颈部融合部分,专门用于关键点检测。SDFM模块(Surface Detail Fusion Module,表层细节融合模块) 通过在特征提取网络的浅层引入通道-空间注意力机制,动态生成深层与浅层特征融合权重。该模块可自适应保留不同模态中的独特信息,抑制背景噪声与光照干扰,实现低层细节的精准对齐与互补增强,为后续检测提供高保真度的底层特征表示,从而提升模型在复杂场景下的目标检测鲁棒性与定位准确性。Rethinking the necessity of ima

Limiiiing的博客 177

python中装饰器的使用教程详解(wraps)

python中装饰器的使用教程详解(wraps)

IT之一小佬的博客 6304

道威棱镜的设计参考

道威棱镜的设计参考

weixin_72050316的博客 383

python wrapper装饰器_Python基础(十四)—装饰器 wrapper

装饰器 wrapper装饰器的作用装饰器的作用就是为已经存在的函数或对象添加额外的功能。装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续...

weixin_31100203的博客 964

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

python装饰器wrapper

原文地址 分类目录——py基础 装饰器,顾名思义,为函数额外装饰一些功能 通过这么一个例子来解释装饰器存在的意义,假使我写了几个函数来实现同一个需求,我想测试一下这个函数的效率,通过测运行耗时的方法。但是,如果在每个函数中都去写同样的测时间的操作,三五个函数还好说,一旦想测的函数多了,这个工作量就~~~ 装饰器就是这样一种机制,只需要在一个函数定义时添加一个标记,就可以给该函数执行前后添加装饰的内...

BBJG_001的博客 2399

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

python wrapper装饰器

参考 将 @debug 放在say_hello() 前面,相当于执行了 say_hello = debug(say_hello) 由于debug()是一个装饰器,返回了wrapper函数,所以原来的say_hello()依然存在,只是现在同名的now变量指向了新的函数,于是调用say_hello()将执行新的函数,即在debug()函数中返回的wrapper()函数。 def debug(func): #2 def wrapper(): #3,8 print('[DEBUG]

weixin_44416759的博客 479

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Python基础篇:闭包、装饰器wrapper

函数定义可以嵌套函数,这在其它语言中也经常见到,但是可以嵌套多层函数还是很少见到。

人不风流枉少年 267

Python装饰器的执行顺序

说到Python装饰器的执行顺序,有很多半吊子张口就来:靠近函数名的装饰器先执行,远离函数名的装饰器后执行。这种说法是不准确的。这个装饰器靠近函数名,是内层装饰器,它里面的print先打印出来;远离函数名,是外层装饰器,它里面的print后打印出来。看起来确实是。为什么我说这种看法是不准确呢?上面这个代码的运行效果如下图所示:从图中可以看到,装饰器里面的代码中,wrapper闭包外面的代码确实是内层装饰器先执行,外层装饰器后执行。但是在闭包wrapperfunc()

Trb201013的博客 1105

装饰器partial、update_wrapper、wraps作用以及如何使用

装饰器partial、update_wrapper、wraps作用以及如何使用 在讲解partial、update_wrapper、以及wraps之前需要了解下装饰器:装饰器在实现的时候,被修饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生比变化)。因此,为了不影响,python使用wraps来消除这样的副作用,因此,在我们写装饰器的时候,最好在实现之前加上wraps,它能保留原有函数

千生百世,缘起缘灭,皆已注定。 3598

python wrapper装饰器_不懂Python装饰器,你敢说会Python?

对于Python学习者,一旦过了入门阶段,你几乎一定会用到Python的装饰器。它经常使用在很多地方,比如Web开发,日志处理,性能搜集,权限控制等。还有一个极其重要的地方,那就是面试的时候。对,装饰器是面试中最常见的问题之一!实战入门抛出问题看这段代码:代码中定义了3个函数,然后分别调用这3个函数。假设,我们发现代码运行很慢,我们想知道每个函数运行分别花了多少时间。笨办法解决我们可以在每个函数中...

weixin_39608134的博客 249

python decorator wrapper_python 的装饰器(Decorator)

先看一个例子#这个是一个闭包,闭包前面已经说了deflog(func):def wrapper(*args, **kw):print('call %s():' % func.__name__)return func(*args, **kw)returnwrapper@logdefnow():print('2015-3-25')#调用函数now()#输出call now():2015-3-25在我们...

weixin_39556474的博客 113

python functools update_wrapper,wraps使用

update_wrapper 使用 此函数主要用在装饰器函数中,装饰器返回函数反射得到的是包装函数的函数定义而不是原始函数定义 如下代码 整合update_wrapper源码 和 示例代码在一个文件中,方便查看; # -*- coding: utf-8 -*- """ (C) Guangcai Ren <rgc@bvrft.com> All rights reserved cr...

rgc_520_zyl的博客 1227

装饰器-wrapper

我跟别人说我精通python,别人问我wrapper是啥,我说不知道,尼玛,原来wrapper就是装饰器,熟的不得了啊,英语真是我的克星啊。 闭包 closure 在认识装饰器之前先认识下闭包 闭包,顾名思义就是把什么东西封闭在保内,什么东西呢?变量和函数。 在一个函数里装了另一个函数,里面那个函数称为内部函数,外面那个函数称为外部函数, 在内部函数里,对在外部作用域(非...

weixin_30340617的博客 133

python @warps装饰器及源码剖析

python装饰器的原理是将装饰对象传入,将装饰对象加强后再返回,但是我们此时调用装饰对象的时候,其实是调用装饰器对象,如下: @decorator def fn(): pass @语法糖其实相当于decorator(fn) python这种动态语言很多功能是以鸭子方式来实现的,即看着像鸭子,游着像鸭子我们就认为它是鸭子 这个也是一样,我们虽然调用的是装饰器,但是实现的效果一样...

renyiforever的博客 3184

python自学——装饰器

装饰器的进化,无参装饰器和有参装饰器

叶子的博客 951

【Python装饰器】functools.wraps函数保留被装饰函数的元信息

前言 除注册装饰器外,大多数装饰器会返回与被装饰函数不同的函数,为与后文保持一致,假设返回的函数叫做wrapper,也可以是其他可调用对象,被装饰的函数叫做func。通过语法糖的形式装饰func会产生一个明显的副作用,就是此时的func本质是wrapper,显示func的属性展示的也是wrapper的属性信息,可以通过wraps装饰器解决此问题。但要想深入理解wraps装饰器,需要先了解functools中的update_wrapper与partial。 update_wrapper函数 update_wr

weixin_44815943的博客 1053
上一篇: Python基础(十二)—面向对象拾遗(__slots__、@property、枚举类、元类)
下一篇: Python-OpenCV图像识别学习
luoz_python
博客等级 码龄10年 57粉丝 47原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值