聊聊Python中的@符号是什么意思

Python中的@符号是装饰器的意思。Python中装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象(函数的指针)。

  • 实质:是一个函数
  • 参数:是你要装饰的函数名(并非函数调用)
  • 返回:是装饰完的函数名(也不是函数调用)
  • 作用:为已经存在的对象添加额外的功能。
  • 特点:不需要对对象做任何的代码上的变动。

Python装饰器有很多经典的应用场景,比如:插入日志,性能测试,事务处理,权限校验等。装饰器是解决这类问题的绝佳设计。

装饰器最大的作用就是对于我们已经写好的程序,我们可以抽离出一些雷同的代码组件多个特定的装饰器,这样我们就可以针对不同的需求去使用特定的装饰器,这时,因为源码去除了大量泛化的内容而使得源码具有更加清晰的逻辑。

定义一个能打印日志的doctorator:

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

@log
def now():
    print('2021-3-25')

if __name__ == '__main__':
    now()

执行结果:

函数对象有一个__name__属性,可以拿到函数的名字。

调用now()函数,不仅会运行now()函数本身,还会在运行now()函数前打印一行日志。

把@log放到now()函数的定义处,相当于执行了语句:

now = log(now)

wrapper()函数的参数定义是(*args,**kw),因此,wrapper()函数可以接收任意参数的调用。在wrapper()函数内,首先打印日志,再紧接着调用原始函数。

如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数:

def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('execute')
def now():
    print('2015-3-25')

if __name__ == '__main__':
    now()

执行结果:

和两层嵌套的decorator相比,3层嵌套的效果是这样的:

now = log('execute')(now)

首先执行log(‘execute'),返回的是decorator函数,再调用返回的函数,参数就是now函数,返回值最终是wrapper函数。

函数也是对象,它有__name_等属性,但你去看经过decorator装饰之后的函数,他们的__name__已经从原来的'now'变成了'wrapper':

print(now.__name__) #输出:wrapper

因为返回的那个wrapper()函数名字就是'wrapper',所以,需要把原始函数的__name__等属性赋值到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

Python内置的functiontools.wraps就是干这个事的,所以,一个完整的decorator的写法如下:

import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

或者

import functools

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

总结

到此这篇关于Python中@符号是什么意思的文章就介绍到这了,更多相关Python中@符号内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们以装饰函数为例子介绍其用法.要理解在Python中装饰器的原理,需要一步一步来.本文尽量描述得浅显易懂,从最基础的内容讲起. (注:以下使用Python3.5.1环境) 一.Python的函数相关基础 第一,必须强调的是python是从上往下顺序执行的,而且碰到函数的定义代码块是不会立即执行它的,只

  • 深入理解python中的闭包和装饰器

    python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). 以下说明主要针对 python2.7,其他版本可能存在差异. 也许直接看定义并不太能明白,下面我们先来看一下什么叫做内部函数: def wai_hanshu(canshu_1): def nei_hanshu(canshu_2): # 我在函数内部有定义了一个函数 return canshu_1*canshu_2 return

  • Python中的装饰器用法详解

    本文实例讲述了Python中的装饰器用法.分享给大家供大家参考.具体分析如下: 这里还是先由stackoverflow上面的一个问题引起吧,如果使用如下的代码: 复制代码 代码如下: @makebold @makeitalic def say():    return "Hello" 打印出如下的输出: <b><i>Hello<i></b> 你会怎么做?最后给出的答案是: 复制代码 代码如下: def makebold(fn):    

  • python 一篇文章搞懂装饰器所有用法(建议收藏)

    01. 装饰器语法糖 如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上.和这个函数绑定在一起.在我们调用这个函数的时候,第一件事并不是执行这个函数,而是将这个函数做为参数传入它头顶上这顶帽子,这顶帽子我们称之为装饰函数 或 装饰器. 你要问我装饰器可以实现什么功能?我只能说你的脑洞有多大,装饰器就有多强大. 装饰器的使用方法很固定: 先定义一个装饰函数(帽子)(也可以

  • Python中装饰器高级用法详解

    在Python中,装饰器一般用来修饰函数,实现公共功能,达到代码复用的目的.在函数定义前加上@xxxx,然后函数就注入了某些行为,很神奇!然而,这只是语法糖而已. 场景 假设,有一些工作函数,用来对数据做不同的处理: def work_bar(data): pass def work_foo(data): pass 我们想在函数调用前/后输出日志,怎么办? 傻瓜解法 logging.info('begin call work_bar') work_bar(1) logging.info('cal

  • python装饰器简介---这一篇也许就够了(推荐)

    Python装饰器(decorator)是在程序开发中经常使用到的功能,合理使用装饰器,能让我们的程序如虎添翼. 装饰器引入 初期及问题诞生 假如现在在一个公司,有A B C三个业务部门,还有S一个基础服务部门,目前呢,S部门提供了两个函数,供其他部门调用,函数如下: def f1(): print('f1 called') def f2(): print('f2 called') 在初期,其他部门这样调用是没有问题的,随着公司业务的发展,现在S部门需要对函数调用假如权限验证,如果有权限的话,才

  • Python中的各种装饰器详解

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: 复制代码 代码如下: >>> def test(func):     def _test():         print 'Call the function %s().'%func.func_name         return func()     return _test >

  • Python装饰器用法实例总结

    本文实例讲述了Python装饰器用法.分享给大家供大家参考,具体如下: 一.装饰器是什么 python的装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.简单的说装饰器就是一个用来返回函数的函数. 它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓存.权限校验等场景.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用. 概括的讲,装饰器的作用就是为已经

  • 聊聊Python中的@符号是什么意思

    Python中的@符号是装饰器的意思.Python中装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象(函数的指针). 实质:是一个函数 参数:是你要装饰的函数名(并非函数调用) 返回:是装饰完的函数名(也不是函数调用) 作用:为已经存在的对象添加额外的功能. 特点:不需要对对象做任何的代码上的变动. Python装饰器有很多经典的应用场景,比如:插入日志,性能测试,事务处理,权限校验等.装饰器是解决这类问题的绝佳设计. 装饰器

  • 聊聊Python中的pypy

    PyPy是一个虚拟机项目,主要分为两部分:一个Python的实现和 一个编译器 PyPy的第一部分: 用Python实现的Python 其实这么说并不准确,准确得说应该是用rPython实现的Python,rPython是Python的一个子集,虽然rPython不是完整的Python,但用rPython写的这个Python实现却是可以解释完整的Python语言. PyPy的第二部分:编译器 这是一个编译rPython的编译器,或者说这个编译器有一个rPython的前端,目前也只有这么一个前端,

  • 聊聊python中的异常嵌套

    在Python中,异常也可以嵌套,当内层代码出现异常时,指定异常类型与实际类型不符时,则向外传,如果与外面的指定类型符合,则异常被处理,直至最外层,运用默认处理方法进行处理,即停止程序,并抛出异常信息.如下代码: try: try: raise IndexError except TypeError: print('get handled') except SyntaxError: print('ok') 运行程序: Traceback (most recent call last): File

  • 聊聊python中的循环遍历

    python之循环遍历 关于循环遍历大家都知道,不外乎for和while,今天我在这写点不一样的循环和遍历.在实践中有时会遇到删除列表中的元素,那么循环遍历列表删除指定元素该怎么做呢? 还是直接上代码看案例吧: import time # 删除下面列表中所有张姓元素,输出的结果应该是['李老大','李老二'] lst = ['张老大', '张老二', '李老大', '张老三', '李老二']*10000 # 直接for循环遍历列表,remove需要删除的元素 def del1(lst): for

  • Python中的//符号是什么意思呢

    目录 //符号是什么意思 /与//的区别 举例 Python算术运算符 //符号是什么意思 Python中的//是向下取整的意思 a//b,应该是对除以b的结果向负无穷方向取整后的数 举例: 5//2=2(2.5向负无穷方向取整为2),同时-5//2=-3(-2.5向负无穷方向取整为-3) /与//的区别 Python语言中/与//的区别是什么? 在Python中/表示浮点整除法,返回浮点结果,也就是结果为浮点数;而//在Python中表示整数除法,返回大于结果的一个最大的整数,意思就是除法结果

  • 聊聊Python中的浮点数运算不准确问题

    大家好,老 Amy 来了.之前就意识到一个问题,但是最近又有朋友提出来了,所以就想着干脆记录下来,分享给大家叭~ 啥问题呢?请看题: 也就是说,需要大家计算1.1-1的值,很多朋友会说:"emmm-这还不简单,玩我呢?不就是0.1嘛" 但是如果你用 python 去执行一下,会发现结果跟你想的不太一样,如下图: 这样大家是不是发现了什么问题?是的,浮点数在运算过程中并没有保证完全精确,是什么原因导致了这种现象呢?很多朋友就会窃喜:"这不就是 Python 的 bug 嘛~&q

  • 聊聊python中not 与 is None的区别

    原因: list 获得的数据为空: 显示值为 [ ] 不同的判断--- is None ----not 两者结果不一样分析: 总之: not 判断的是内容,而is None则涉及到这个 list 或 dict 是否声明并定义 补充:关于Python not 及is None的有趣现象(两者的区别) 笔者小白最近在刷题的过程中,遇到一个有趣的现象. 在使用 if A is None 来实现判断条件的时候,最后程序没有通过.这里的A代表之前定义的list类型的数据.最用改成if not A才通过.

  • 聊聊Python中end=和sep=的区别

    end: 默认是换行,表示两个字符串最后以什么结尾. eg: 换行 end="\n" sep: 默认是空格,表示两个字符串之间用什么分割. eg: 空格 sep=" " 补充:python 中的 print(x, end=) 和 print(x, sep=) print(x, end=) for i in range(10): print(i) 输出结果: 0 1 2 3 4 5 6 7 8 9 for i in range(10): print(i, end=&q

  • 聊聊python中的load、loads实现反序列化的问题

    load与loads 简介: 在python自动化中,我们传递一些参数是需要从文件中读取过来的,读取过来的字典并非python对象数据类型而是string类型. 这样在我们传递参数的时候就会出现格式不正确的情况,这时候就要用到load实现反序列化 python对象数据类型包括list ,dict,tuple,set等 案例1:load load:load主要处理的是文件流 首先我们新建一个txt文件,文件中写入一个字典 {"a":"1","b":

  • 简单聊聊Python中的鸭子类型和猴子补丁

    目录 前言 鸭子类型 猴子补丁 总结 前言 Python 开发者可能都听说过鸭子类型和猴子补丁这两个词,即使没听过,也大概率写过相关的代码,只不过并不了解其背后的技术要点是这两个词而已. 我最近在面试候选人的时候,也会问这两个概念,很多人答的也并不是很好.但是当我向他们解释完之后,普遍都会恍然大悟:“哦,是这个啊,我用过”. 所以,我决定来写一篇文章,探讨一下这两个技术. 鸭子类型 引用维基百科中的一段解释: 鸭子类型(duck typing)在程序设计中是动态类型的一种风格.在这种风格中,一个

随机推荐