装饰器:(语法糖)

本质是函数,它是赋予函数新功能,但是不改变函数的源代码及调用方式
 
原则:
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. Java发送邮件功能

    package com.hd.all.test.testjava; import java.util.Properties; import javax.mail.Address; import jav ...

  2. Python3.6安装使用tesserocr文件时遇到问题

    本机运行环境: Win 10 version 1709; Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit ...

  3. python frist lesson

    1.print("") 代表打印字符段 2.name2 = name ,然后改变name的赋值,name2的值还是以前name的值,说明name2指向的是内存中name的赋值. 3 ...

  4. html5dom2

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  5. Java 五大原则

    1.单一职责 不论是在设计类,接口还是方法,单一职责都会处处体现,单一职责的定义:我们把职责定义为系统变化的原因.所有在定义类,接口,方法的时候.定义完以后再去想一想是不能多于一个的动机去改变这个类, ...

  6. 反向代理&集线器和交换机的区别&广播地址&seq与ack的区别

    反向代理服务器: 当一个代理服务器能够代理外部主机访问内部网络时,这种代理服务的方式称为反向代理服务,该服务器被称为反向代理服务器. 集线器与交换机的区别: 集线器和交换机都是起到端口转发的作用,不同 ...

  7. select2的用法

    <link href="../css/select2.min.css" rel="stylesheet" /> <script src=&qu ...

  8. IDEA循环依赖报错解决方案

    step1.查找循环依赖 step2.在IDEA菜单栏中打开Analyze->Analyze Module Dependencies...看到有的模块被红色的标出来了,此时右边显示了循环依赖,那 ...

  9. spool例子

    set head offset echo offset feed offset heads offset pages 50000SET NEWPAGE NONEcolumn yesterday new ...

  10. css的再深入7(更新中···)

    1.transparent  透明的 2.placeholder  提示语 写页面 搞清结构层次, 保证模块化,让他们之间不能受到影响 (1) 元素性质 (2) 标准流 浮动带来的脱离文档流撑不起父级 ...