装饰器:(语法糖)

本质是函数,它是赋予函数新功能,但是不改变函数的源代码及调用方式
 
原则:
1.不能修改被装饰函数的源代码
2.不能修改被装饰函数的调用方式
3.函数的返回值也不变
这两点简而言之,就是装饰器对被装饰函数来说是透明的
 
知识储备
1.函数即变量
     比如定义了一个变量  x = ‘gkx’   python是一门解释性语言,解释了‘gkx’,并给它分配了内存地址,而 x 就是这个内存地址的一个索引,类似门牌号。
同理可得 def test():print('gkx') 定义了一个函数  test是它的门牌号,print('gkx')分配了一个内存地址。故可以理解为函数即变量。
2.高阶函数
    a.把一个函数名当作实参传递给另外一个函数(在不改变函数源代码的情况
为其添加新功能)
    b.返回值中包含函数名(不改变函数调用方式
3.嵌套函数
 嵌套函数  在一个函数的函数体内,用def声明一个新函数
def foo():
print('in the foo.')
def bar():
print('in the bar.')
bar() #要调用bar需要在在函数体内调用,类似局部变量
foo()

装饰器例子:仅针对注释的几段,对其进行排序,如下红字

 import time       #python的debug都是先读取最外层框架(最外层没有缩进),最外层中如果涉及到调用,再接着运行调用内容。  第一步

 def timer(func): #当读取到 @timer的时候,相当于运行 test1 = timer(test1),所以会返回来读取 warpper  第三步
def warpper(*args,**kwargs):
start_time = time.time()
func(*args,**kwargs)  #此时才是真正意义上运行 test1函数 第六步
       return func(*args,**kwargs) #保证fun()返回值也不变
stop_time = time.time()
print('in the test1() %s'%(stop_time-start_time))
return warpper #把test1当作实参传递给 timer,timer(test1),此时返回的是 函数warpper的内存地址 第四步 #然后此时运行到 python里的语法【@timer】
@timer #相当于 test1 = timer(test1),返回warpper的内存地址,此时如果运行 test1(),相当于 warpper(),warpper就开始执行其函数体内的语句 第二步
def test1():
time.sleep(1)
print('in the test1')
    return ‘from test1’
test1() #此时运行的 test1()已经不是直接运行 test1函数了,是经过@timer,转换成运行 warpper()了 第五步

 装饰器进阶版,装饰器本身带参数

 user = 'gkx'
pass_1 = ''
def decorator(auth_type):
print("auth type",auth_type)
def outer_warpper(func):
def warpper(*args,**kwargs):
if auth_type == 'local':
username = input("id")
password = input("password")
if username == user and password == pass_1:
print('\033[32;1mwelcome\033[0m')
res = func(*args,**kwargs)
print("after decorator")
return res
else:
print('\033[31;1mwrong info\033[0m')
elif auth_type == 'ldap':
print('我不会')
return warpper
return outer_warpper #当访问到这里的返回值时候,会继续执行 warpper,然后执行逻辑就和上面提到的timer一样了 @decorator(auth_type='local')  #这里分成两部分看,第一部分是 调用decorator(auth_type = 'local'),此时返回outer_wrapper的内存地址
                    #在第一部分的基础上,此时加上@,变成了 @outer_wrapper,相当于 homepage = outer_wrapper(wrapper),再返回了wrapper的内存地址 def homepage():
26   print('home page')
   return 'from home'

 @decorator(auth_type='ldap')
def bbs():
print('in bbs') print(homepage())
bbs()

装饰器三个重要补充:

#一共有三个

# 第一个
from functools import wraps def outer(func):
@wraps(func) #wraps模块
def inner(*args,**kwargs):
print('装饰前')
ret = func(*args,**kwargs)
print('装饰后')
return ret
return inner @outer
def holiday(day):
''' :param day: days of vacation
:return:
'''
print("放假%s"%day)
return '好开心' print(holiday.__name__) #import wraps后此时打印holiday函数名,否则是 inner函数名
print(holiday.__doc__)
ret = holiday(3)
print(ret) # 第二个,当装饰器带参数
import time
FLAG = False
def out_timmer(flag):
def timmer(func):
def inner(*args,**kwargs):
if flag:
start = time.time()
ret = func()
end = time.time()
print(start-end)
return ret
else:
ret = func()
return ret
return inner
return timmer
@out_timmer(FLAG) #可以看成两部 1, timmer = out_timmer(FLAG) 2, @timmer
def shop1():
time.sleep(0.01)
print('buy first thing') @out_timmer(FLAG)
def shop2():
time.sleep(0.01)
print('buy second thing') shop1()
shop2() #第三个 函数被多个装饰器调用
def wrapper1(func): #func-----> f
def inner1():
print('wrapper1,befor func')
ret = func()
print('wrapper1,after func') #这一句运行完,但是inner2还没结束,要返回inner2继续运行【print('wrapper2,after func')】
return ret
return inner1 def wrapper2(func): #func-----> inner1 inner1传给了wrapper2
def inner2():
print('wrapper2,befor func') #运行完这一句,下一句运行inner1,故返回到wrapper1继续运行
ret = func() #inner1
print('wrapper2,after func')
return ret
return inner2 @wrapper2 #wrapper1 执行完后,执行wrapper2 但是此时传入的不是f,是 inner1,相当于 wrapper(inner1) == inner2 然后继续运行warpper2
@wrapper1 #先执行到这里,因为语法糖要找离它最近的函数。wrapper2没找到,故往下运行。此时函数 f传给wrapper1 相当于 f = wrapper1(f) 即为 inner1
def f():
print('in the f')
f() #--------->>调用inner2

Python—装饰器详解的更多相关文章

  1. Python装饰器详解

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

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

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

  3. Python中的各种装饰器详解

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

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

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

  5. python函数装饰器详解

    python装饰器(fuctional decorators)简单来说就是修改其他函数的函数. 这样的函数需要满足两个个条件: 1.不能修改原函数的源代码 2.不能改变原函数的调用方式 需要达到的效果 ...

  6. python之装饰器详解

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

  7. python装饰器1:函数装饰器详解

    装饰器1:函数装饰器 装饰器2:类装饰器 装饰器3:进阶 先混个眼熟 谁可以作为装饰器(可以将谁编写成装饰器): 函数 方法 实现了__call__的可调用类 装饰器可以去装饰谁(谁可以被装饰): 函 ...

  8. python 叠加装饰器详解

    def out1(func1): #7.func1=in2的内存地址,就是in2 print('out1') def in1(): #8.调用函数index() 因为函数在in1里,所以首先运行in1 ...

  9. (转)面向对象(深入)|python描述器详解

    原文:https://zhuanlan.zhihu.com/p/32764345 https://www.cnblogs.com/aademeng/articles/7262645.html----- ...

随机推荐

  1. numpy 性能提升

    a = np.array([1,2,3,4,5,1,2,2,2])c = np.unique(a)print(c) 对于很大的稀疏矩阵,我们不能用a[a>0]去取大于0的元素,而应该使用np.w ...

  2. Python openpyxl、pandas操作Excel方法简介与具体实例

    本篇重点讲解windows系统下 Python3.5中第三方excel操作库-openpyxl: 其实Python第三方库有很多可以操作Excel,如:xlrd,xlwt,xlwings甚至注明的数据 ...

  3. Ocelot:API网关概要

    一.概要 Ocelot是.Net Core下一个开源API网关:Ocelot主要目标是在.NET在微服务或面向服务架构中提供统一的入口服务, Ocelot拿到HttpRequest对象到管道后,先创建 ...

  4. WIN7虚拟桌面创建(多屏幕多桌面)

    Windows7/WIN7虚拟桌面怎么用怎么创建多桌面(摘录) 在使用电脑中经常会遇到桌面软件太多了不够用的感慨,那么要是一台电脑有多个桌面就好了.在windows10中自带已经支持了虚拟桌面,在wi ...

  5. Unity之显示fps功能

    如下: using UnityEngine; using System.Collections; public class ShowFpsOnGUI : MonoBehaviour { public ...

  6. laravel容器container 阅读记录

    今天抽时间又仔细看了一下laravel的container,记录一下. 所谓容器,听名字就知道,是一个仓库,装东西用的,所以,container所有的功能,都围绕一个主题:管理装. 类名称:Illum ...

  7. Mysql报错:Packet for query is too large (1121604 > 1048576).You can change this value on the server by setting the max_allowed_packet variable

    看错误信息,发现1048576个字节,正好是1*1024*1024byte,也就是1Mb. 这正是mysql默认的max_allowed_packet值. 使用sql语句: show VARIABLE ...

  8. Java解决异常之try、catch、finally、throw、throws&log4j记录日志步骤

    知识点一.多重catch引发多种类型的异常排列catch 语句的顺序:先子类后父类 发生异常时按顺序逐个匹配只执行第一个与异常类型匹配的catch语句二.异常分类异常分为运行时异常和检测异常运行时异常 ...

  9. 【Python】【自动化测试】【pytest】【常用命令行选项】

    https://www.cnblogs.com/cnkemi/p/9989019.html http://www.cnblogs.com/cnkemi/p/10002788.html pytest 常 ...

  10. 2017 Russian Code Cup (RCC 17), Final Round

    2017 Russian Code Cup (RCC 17), Final Round A Set Theory 思路:原题转换一下就是找一个b数组,使得b数组任意两个数的差值都和a数组任意两个数的差 ...