本章结构:

1.理解装饰器的前提准备

2.装饰器:无参/带参的被装饰函数,无参/带参的装饰函数

3.装饰器的缺点

4.python3的内置装饰器

5.本文参考

理解装饰器的前提:1.所有东西都是对象(函数可以当做对象传递) 2.闭包

闭包的概念:
1)函数嵌套
2)内部函数使用外部函数的变量
3)外部函数的返回值为内部函数

下面写一个最为简单的闭包的例子:

 def test(name):
def test_in():
print(name)
return test_in func = test('whyz')
func()

装饰器的原型:

 import time
def showtime(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) return wrapper def foo():
print('foo..')
time.sleep(3) foo = showtime(foo)
foo()

不带参数的装饰器:(装饰器,被装饰函数都不带参数)

 import time
def showtime(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) return wrapper @showtime #foo = showtime(foo)
def foo():
print('foo..')
time.sleep(3) @showtime #doo = showtime(doo)
def doo():
print('doo..')
time.sleep(2) foo()
doo()

带参数的被装饰的函数

 import time
def showtime(func):
def wrapper(a, b):
start_time = time.time()
func(a,b)
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) return wrapper @showtime #add = showtime(add)
def add(a, b):
print(a+b)
time.sleep(1) @showtime #sub = showtime(sub)
def sub(a,b):
print(a-b)
time.sleep(1) add(5,4)
sub(3,2)

带参数的装饰器(装饰函数),

实际是对原有装饰器的一个函数的封装,并返回一个装饰器(一个含有参数的闭包函数),
当使用@time_logger(3)调用的时候,Python能发现这一层封装,并将参数传递到装饰器的环境去

 import time
def time_logger(flag = 0):
def showtime(func):
def wrapper(a, b):
start_time = time.time()
func(a,b)
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) if flag:
print('将此操作保留至日志') return wrapper return showtime @time_logger(2) #得到闭包函数showtime,add = showtime(add)
def add(a, b):
print(a+b)
time.sleep(1) add(3,4)

类装饰器:一般依靠类内部的__call__方法

 import time
class Foo(object):
def __init__(self, func):
self._func = func def __call__(self):
start_time = time.time()
self._func()
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) @Foo #bar = Foo(bar)
def bar():
print('bar..')
time.sleep(2) bar()

使用装饰器的缺点:

1.位置错误的代码->不要在装饰器之外添加逻辑功能
2.不能装饰@staticmethod 或者 @classmethod已经装饰过的方法
3.装饰器会对原函数的元信息进行更改,比如函数的docstring,__name__,参数列表:

下面对装饰器第第三个缺点进行剖析,

 import time
def showtime(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) return wrapper @showtime #foo = showtime(foo)
def foo():
print('foo..')
time.sleep(3) def doo():
print('doo..')
time.sleep(2) print(foo.__name__)
print(doo.__name__)

结果为:

wrapper
doo

由此可以看出,装饰器会对原函数的元信息进行更改,可以使用wraps,进行原函数信息的添加

注解:wraps本身也是一个装饰器,他能把函数的元信息拷贝到装饰器函数中使得装饰器函数与原函数有一样的元信息

以下是一个wraps的例子:

 import time
from functools import wraps
def showtime(func): @wraps(func)
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print('spend is {}'.format(end_time - start_time)) return wrapper @showtime #foo = showtime(foo)
def foo():
print('foo..')
time.sleep(3) def doo():
print('doo..')
time.sleep(2) print(foo.__name__)
print(doo.__name__)

结果为:

foo
doo

常用的内置装饰器:1.staticmethod: 类似实现了静态方法 注入以后,可以直接 : 类名.方法

2.property:经过property装饰过的函数 不再是一个函数,而是一个property,类似实现get,set方法

 @property
def width(self):
return self.__width @width.setter
def width(self, newWidth):
self.__width = newWidth

3.classmethod: 与staticmethod很相似,貌似就只有这一点区别:
第一个参数需要是表示自身类的 cls 参数,
可以来调用类的属性,类的方法,实例化对象等。

本文参考:

1.https://www.cnblogs.com/vamei/archive/2013/02/16/2820212.html

2.https://www.cnblogs.com/wupeiqi/articles/4980620.html

3.https://www.cnblogs.com/yuanchenqi/articles/5830025.html

4.https://blog.csdn.net/mdzzname/article/details/78702440

python3 装饰器全解的更多相关文章

  1. jquery系列教程1-选择器全解

    全栈工程师开发手册 (作者:栾鹏) 快捷链接: jquery系列教程1-选择器全解 jquery系列教程2-style样式操作全解 jquery系列教程3-DOM操作全解 jquery系列教程4-事件 ...

  2. python设计模式之装饰器详解(三)

    python的装饰器使用是python语言一个非常重要的部分,装饰器是程序设计模式中装饰模式的具体化,python提供了特殊的语法糖可以非常方便的实现装饰模式. 系列文章 python设计模式之单例模 ...

  3. 净心诀---python3装饰器

    python3装饰器 装饰器作用 简单理解:可以为已有函数添加额外功能 例: 已有2个函数如下 def MyFunc1(): print("This is a print function1 ...

  4. Python全栈开发之8、装饰器详解

    一文让你彻底明白Python装饰器原理,从此面试工作再也不怕了.转载请注明出处http://www.cnblogs.com/Wxtrkbc/p/5486253.html 一.装饰器 装饰器可以使函数执 ...

  5. Python装饰器的解包装(unwrap)

    在Python 3.4 中,新增一个方法unwrap,用于将被装饰的函数,逐层进行解包装. inspect.unwrap(func, *, stop=None) unwrap方法接受两个参数:func ...

  6. python3 装饰器应用举例

    [引子] python 中的装饰器是oop(面向对象编程)设计模式.之装饰器模式的一个应用.由于有语法糖衣的缘故.所以写起来也更加方便 [从一个比较经典的应用场景来讲解装饰器] 有过一定编程经历的工程 ...

  7. python3 装饰器

    #Author by Andy#_*_ coding:utf-8 _*_#装饰器的原则及构成:# 原则:# 1.不能修改被装饰函数的源代码.# 2.不能修改被装饰函数的调用方式.# 3.不能改变被装饰 ...

  8. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  9. python之装饰器详解

    这几天翻看python语法,看到装饰器这里着实卡了一阵,最初认为也就是个函数指针的用法,但仔细研究后发现,不止这么简单. 首先很多资料将装饰器定义为AOP的范畴,也就是Aspect Oriented ...

随机推荐

  1. 如何找出长时间未提交的事务session ID

    收到报警某台mysql数据库慢查询数量超过5,登录上去看,发现阻塞的SQL全部是update,处于Updating状态 +---------+------+-----------+------+--- ...

  2. Java Bad version

    Eclipse的三个地方需要重新设置: 在工程上点右键,选属性,三个地方: Java Build Path Java Compiler Project Facets:这个地方还可以设置tomcat的r ...

  3. vue-cli的工程如何正确使用Google Analytics?

    前言 最方便的方法,莫过于使用vue-analytics:https://github.com/MatteoGabriele/vue-analytics. 包是有了,可是真正使用起来会发现Google ...

  4. MySQL5.6.12 rpm制作及及自动化部署安装

    转自:http://blog.itpub.net/29254281/viewspace-1268918/ 首先,下载rpmbuildyum install rpm-build -y它是Red Hat用 ...

  5. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(五)——实现注册功能

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  6. [android] 手机卫士黑名单功能(ListView优化)

    上一篇记录了使用ListView展示出来了100条数据,当慢慢拖动的时候,不会有问题,但是当拖动很快的时候,应用会报anr错误 查看错误日志,看到报OutOfMemoryError,内存不足 List ...

  7. 【转】从msql数据库处理高并发商品超卖

    今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过:但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识.今天就我的一些理解,整理一下 ...

  8. JAVA中的泛型(Generic)

    Java泛型(Generic)简介 泛型是jdk1.5版本以后推出来的,表示类型参数化,让java能更具有动态性一些,让类型能变成参数传递. 要我自己感觉的话,泛型本身没啥用,跟反射在一起用,就体现出 ...

  9. 后台管理UI+功能

    kingRoad功能强大,丰富各种功能和插件,自定义开发功能组件及样式,使用webpack方式集成和纯html两种,UI(自定义开发和AdminLTE的集成优化),弹窗功能使用(Layer弹窗,并与框 ...

  10. 关于pycharm 打不开某些文件夹和文件打不开的问题

    在使用pycharm的时候遇到了一个情况, 下载了一个文件,自己修改了文件夹名称后再打开文件夹里的py文件, 打不开了,pycharm没有反应, 百度了一下,没有类似的问题,觉得应该是个个例... 然 ...