装饰器:(语法糖)

本质是函数,它是赋予函数新功能,但是不改变函数的源代码及调用方式
 
原则:
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. 十一、无事勿扰,有事通知(2)——KVO

    概述 Key-Value-Observe,简称KVO,和上节介绍的Notification师出同门,主要目的都是为了实现观察者模式. 虽说是同门师兄弟,但是各自精通的技艺却是各不相同的. 不像Noti ...

  2. 【软件工程1916|W(福州大学)_助教博客】团队第一次作业成绩公示

    题目 第一次作业 评分准则: 队名(最好能够体现项目内容,要求有亮点与个性):(1分) 拟作的团队项目描述:一句话(中英文不限):(1分) 队员风采:介绍每一名队员,包括成员性格.擅长的技术.编程的兴 ...

  3. K-wolf Number (数位DP)

    题意:求区间内有多少个数满足条件:任意相邻的k个数位都不相等. 思路:老套路 #include<bits/stdc++.h> using namespace std; typedef lo ...

  4. Web基础学习---HTML 第一天

    Web基础学习---HTML 第一天 1 HTML标签 2.CSS Web开发基础HTML好吧离开Python几天...如何学好前端?? 多去看别人的网站.多看.多写.多练,(知乎.36Kr.)多练就 ...

  5. bootloader研究最后一关(上)

    2011-03-12 17:03:17 把map文件也仔细看了下.代码及map文件及段分配的关系,可以参考我总结的图.暂时堆栈我就不放在ZI上了.不是今天的重了点 今天重点研究2440的nandfla ...

  6. ArrayList去重

    1.利用HashSet(不保证元素顺序一致) HashSet不会存在相同的元素,可以利用这一点去除List中的重复元素 List<String> beforeList = new Arra ...

  7. button theme

    children:[ButtonTheme.bar( child:ButtonBar( children:[ FlatButton... ], ),), ]

  8. java限制map大小,并FIFO淘汰

    有时候需要往一个MAP中写入一些记录,但又怕无限制地写入会导致内存爆掉,所以得限制这个MAP的大小. 实现:LinkedHashMap提供了简单的方法. 首先,定义一个最大数,比如1000,然后new ...

  9. opencv学习之路(23)、轮廓查找与绘制(二)——访问轮廓每个点

    一.简介 二.画出每个轮廓的每个点 #include "opencv2/opencv.hpp" using namespace cv; void main() { Mat src= ...

  10. 超简单的SpringBoot整合mybatis

      1. 创建项目结构 2. 编写application.yml/application.properties配置文件 3. 启动类开启映射包扫描 4. 接口测试 创建项目结构     导入依赖 &l ...