装饰器

       1、特点:装饰器的作用就是为已存在的对象添加额外的功能,特点在于不用改变原先的代码即可扩展功能;

  2、使用:装饰器其实也是一个函数,加上@符号后放在另一个函数“头上”就实现了装饰的功能,执行被装饰的函数时,其实相当于func(*args, **kwargs) = decorator(func)(*args, **kwargs);

  3、基本原理:在加载装饰器时,也就是加载到@符时,会运行一次装饰器(也就是被@后的函数),它的返回值会替代被装饰的函数地址,而被装饰的函数的地址以装饰器函数参数的形式传进了装饰器。如下示例中:加载到@decorator时,运行了一次decorator()函数,这时函数hello()把函数名(也就是函数地址hello)作为装饰器参数func传了进去,decorator()执行完后返回函数inner()的函数地址,这个函数地址替代了函数hello()的函数地址,当执行hello('Jom')时,就会执行替换后的函数,即inner('Jom'),然后就会去执行inner()函数内的内容。

简单装饰器示例:

 def decorator(func):
print('hello python!') # 相当于给hello添加的额外功能
def inner(name):
print('hello, my friend') # 相当于给hello添加的额外功能
func(name) # func即为hello()函数 return inner @decorator # 装饰器用@表示,函数decorator()装饰函数hello()
def hello(name):
print('hello %s!' % name) hello('Jom') # 执行函数 # 输出--------------------------------------------------------------
# hello python!
# hello, my friend
# hello Jom!

  

装饰器传参示例:

 def decorator_var(var1, var2):
print('decorator_var') # 装饰器的传参,就是在简单装饰器外面再套一层“壳子”
# 并且加载到装饰器的时候,会自动执行decorator_var和decorator两个函数
def decorator(func):
print('decorator') def inner(name):
print(var1, var2)
func(name) return inner return decorator @decorator_var('Python', '')
def hello(name):
print('hello %s!' % name) hello('Jom') # 输出--------------------------------------------------
# decorator_var
# decorator
# Python 36
# hello Jom!

  4、安全防护:被装饰的函数的__name__属性(只测试了这个属性)会被修改为装饰器函数返回的函数名(虽然本质上已经不是在执行原函数了,因为它被装饰了,但是“表面上”我们代码还是执行的是这个函数,所以看起来就是原先的函数的属性被修改了,这样明显就是不安全的),但是为了防止这种不安全的行为,可以使用“from functools import wraps”来装饰器装饰器返回的函数。

 from functools import wraps

 # 装饰器__name__属性防护
def decorator(func):
@wraps(func) # 这个装饰器可以防止被装饰的函数的__name__属性值被修改
def inner(*args, **kwargs): # 可以使用*args和**kwargs为“万能”的传参方式,当然这里也可以写成inner(a, b)
func(*args, **kwargs) return inner # 加载到这个装饰器时,相当于:test_func = decorator(test_func),即test_func = inner
# 如果没有对__name__的保护,加载装饰器后,如:函数test_func的__name__属性就会由“test_func”变为“inner”了
@decorator
def test_func(a, b):
print('sum of a+b: %s' % (a + b))

  

Python笔记:装饰器的更多相关文章

  1. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  2. Python札记 -- 装饰器补充

    本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...

  3. python基础——装饰器

    python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...

  4. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

  5. 两个实用的Python的装饰器

    两个实用的Python的装饰器 超时函数 这个函数的作用在于可以给任意可能会hang住的函数添加超时功能,这个功能在编写外部API调用 .网络爬虫.数据库查询的时候特别有用 timeout装饰器的代码 ...

  6. python 基础——装饰器

    python 的装饰器,其实用到了以下几个语言特点: 1. 一切皆对象 2. 函数可以嵌套定义 3. 闭包,可以延长变量作用域 4. *args 和 **kwargs 可变参数 第1点,一切皆对象,包 ...

  7. 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档

    转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...

  8. python基础—装饰器

    python基础-装饰器 定义:一个函数,可以接受一个函数作为参数,对该函数进行一些包装,不改变函数的本身. def foo(): return 123 a=foo(); b=foo; print(a ...

  9. 详解Python的装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  10. 关于python的装饰器(初解)

    在python中,装饰器(decorator)是一个主要的函数,在工作中,有了装饰器简直如虎添翼,许多公司面试题也会考装饰器,而装饰器的意思又很难让人理解. python中,装饰器是一个帮函数动态增加 ...

随机推荐

  1. STM32F429驱动SDRAM

    1 SDRAM控制原理 1.1 SDRAM信号线 1.2 SDRAM地址线 SDRAM包含有“A”以及“BA”两类地址线: A:行(Row)与列(Column)共用的地址线 BA:独立的用于指定SDR ...

  2. 编译一个支持django及mysqlclient连接的alpine镜像

    一切都不难,难的就是在alpine镜像里. 最后,使用了网上编译好mysqlclient的镜像,才搞定. 记录一下. 一,基础镜像Dockerfile https://github.com/tnir/ ...

  3. 201871010124-王生涛《面向对象程序设计(java)》第四周学习总结

    项目 内容 这个作业属于哪个课程 <任课教师博客主页链接>https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址>http ...

  4. eclipse打可运行的jar

    参考:https://www.cnblogs.com/wangzhisdu/p/7832666.html 用eclipse打包可运行的jar比较坑的地方: 3.1 从下拉框选择该jar的入口文件,即m ...

  5. 使用构造函数 Boolean 创造的对象不是布尔值,而是对象,typeof new Boolean(1) == 'object'

    注意,使用构造函数 Boolean 创造的对象不是布尔值: 事实上 new Boolean() 返回的是一个 Boolean 对象: typeof new Boolean(1) == 'object' ...

  6. LG5338/BZOJ5509/LOJ3105 「TJOI2019」甲苯先生的滚榜 Treap

    问题描述 LG5338 LOJ3105 BZOJ5509 题解 建立一棵\(\mathrm{Treap}\),把原来的\(val\)换成两个值\(ac,tim\) 原来的比较\(val_a<va ...

  7. UML系列

    UML类图:https://www.cnblogs.com/shindo/p/5579191.html UML用例图:https://www.jianshu.com/p/3cde67aed8e9 UM ...

  8. Redis笔记1-Redis介绍及数据类型使用场景

    Redis介绍:C语言开发.单线程操作.高性能.键值对.可持久化的数据库.Redis采用redisObject结构来统一五种数据类型,redisObject是五种类型的父类,可以在函数间传递时隐藏具体 ...

  9. ios、安卓的兼容性

    日期转换成时间戳: 安卓下可以使用 Date.parse(new Date('2019-11-18 12:00:00')) 直接转换,结果为 1574049600000 ios下 Date.parse ...

  10. Codeforces Round #507 (Div. 2, based on Olympiad of Metropolises) D mt19937

    https://codeforces.com/contest/1040/problem/D 用法 mt19937 g(种子); //种子:time(0) mt19937_64 g(); //long ...