被装饰器装饰的函数名即使没有被调用(因为有@xxx,会触发运行装饰器),(装饰器工厂函数)定义装饰器的代码已经运行了(最内部的那个函数并没有运行)(把被装饰的原函数引用赋值给了装饰器内部的那个函数名),当下边通过该函数名调用时,会调用到装饰器内部的那个函数()

装饰器:在不修改函数源代码的基础上,添加函数功能

一个简单的装饰器

def log_time(func):  # 此函数的作用时接受被修饰的函数的引用test,然后被内部函数使用
def make_decorater():
print('现在开始装饰')
func()
print('现在结束装饰')
return make_decorater # log_time()被调用后,运行此函数返回make_decorater()函数的引用make_decorater @log_time # 此行代码等同于,test=log_time(test)=make_decorater
def test():
print('我是被装饰的函数')
test() # test()=make_decorater()
D:\pycharm_project\装饰器\venv\Scripts\python.exe D:/pycharm_project/装饰器/venv/装饰器.py
现在开始装饰
我是被装饰的函数
现在结束装饰 Process finished with exit code 0

当被装饰的函数有形参时

def log_time(func):
def make_decorater(*args,**kwargs): # 接受调用语句的实参,在下面传递给被装饰函数(原函数)
print('现在开始装饰')
test_func = func(*args,**kwargs) # 如果在这里return,则下面的代码无法执行,所以引用并在下面返回
print('现在结束装饰')
return test_func # 因为被装饰函数里有return,所以需要给调用语句(test(2))一个返回,又因为test_func = func(*args,**kwargs)已经调用了被装饰函数,这里就不用带()调用了,区别在于运行顺序的不同。
return make_decorater @log_time
def test(num):
print('我是被装饰的函数')
return num+1 a = test(2) # test(2)=make_decorater(2)
print(a)
D:\pycharm_project\装饰器\venv\Scripts\python.exe D:/pycharm_project/装饰器/venv/装饰器.py
现在开始装饰
我是被装饰的函数
现在结束装饰
3 Process finished with exit code 0

当@装饰器后有参数时

def get_parameter(*args,**kwargs):  # 工厂函数,用来接受@get_parameter('index.html/')的'index.html/'
def log_time(func):
def make_decorater():
print(args,kwargs)
print('现在开始装饰')
func()
print('现在结束装饰')
return make_decorater
return log_time @get_parameter('index.html/')
def test():
print('我是被装饰的函数')
# return num+1 test() # test()=make_decorater()
D:\pycharm_project\装饰器\venv\Scripts\python.exe D:/pycharm_project/装饰器/venv/装饰器.py
('index.html/',) {}
现在开始装饰
我是被装饰的函数
现在结束装饰 Process finished with exit code 0

两个装饰器同时修饰一个函数(重点看执行顺序)

def log_time1(func):
def make_decorater(*args,**kwargs):
print('1现在开始装饰')
test_func = func(*args,**kwargs)
print('1现在结束装饰')
return test_func
return make_decorater def log_time2(func):
def make_decorater(*args,**kwargs): # 接受调用语句的实参,在下面传递给被装饰函数(原函数)
print('2现在开始装饰')
test_func = func(*args,**kwargs) # 如果在这里return,则下面的代码无法执行,所以引用并在下面返回
print('2现在结束装饰')
return test_func # 因为被装饰函数里有return,所以需要给调用语句(test(2))一个返回,又因为test_func = func(*args,**kwargs)已经调用了被装饰函数,这里就不用带()调用了,区别在于运行顺序的不同。
return make_decorater @log_time1
@log_time2
def test(num):
print('我是被装饰的函数')
return num+1 a = test(2) # test(2)=make_decorater(2)
print(a)
D:\pycharm_project\装饰器\venv\Scripts\python.exe D:/pycharm_project/装饰器/venv/装饰器.py
1现在开始装饰
2现在开始装饰
我是被装饰的函数
2现在结束装饰
1现在结束装饰
3 Process finished with exit code 0

注意看执行结果(print,只有执行就会输出到屏幕)(return将数据返回给接受的变量或引用)

def makeBold(fn):
def wrapped1():
print('1')
b = "<b>" + fn() + "</b>" # 此行fn()调用了wrapped(),所以wrapped()执行了print输出到屏幕,然后fn()接受到了wrapped() return返回的结果"<i>" + fn() + "</i>",所以需要等待wrapped()
print('1end') # 只有b = "<b>" + fn() + "</b>"执行完毕才会执行这一行,只有wrapped()函数 return返回后,上一行代码才执行
    return b
return wrapped1 def makeItalic(fn):
def wrapped():
print('2')
a = return "<i>" + fn() + "</i>" # 此行fn()调用了test3(),所以test3()执行了,然后fn()接受到了test3()中returnd返回的结果"hello world-3",所以需要等待test3
print('2end') # 当test3()返回后,上一行代码执行完毕,在屏幕上输出此行
return a
return wrapped @makeBold
@makeItalic
def test3():
return "hello world-3" # return 给了wrapped,wrapped又return给了wrapped; a = test3() # 此行test3() = wrapped1(),test3()调用了函数所以装饰器才执行。a接受了装饰器return的结果
print(a)
D:\pycharm_project\装饰器\venv\Scripts\python.exe D:/pycharm_project/装饰器/venv/text.py
1
2
2end
1end
<b><i>hello world-3</i></b> Process finished with exit code 0

最新文章

  1. Senparc.Weixin.MP SDK 微信公众平台开发教程(十八):Web代理功能
  2. three.js自定义形状
  3. AIX5.3CPU占用高的问题核查
  4. navicat查看mysql数据表记录数不断变化
  5. keytool 生成 Android SSL 使用的 BKS
  6. Hibernate的查询,二级缓存,连接池
  7. BI数据分析中KPI,KGI,CSF概念
  8. 5. SpringBoot —— Actuator简介
  9. 动态DP之全局平衡二叉树
  10. Flume+Kafka+Storm整合
  11. ajax01
  12. linux下安装svn出现configure: error: We require OpenSSL; try --with-openssl
  13. 于dm-0 dm-1
  14. IDEA配置maven,jdk,编码
  15. js中的stopImmediatePropagation方法和stopPropagation方法的区别
  16. 洛谷P3201 [HNOI2009]梦幻布丁(链表 + 启发式合并)
  17. DevExpress 行事历(Scheduler)的常用属性、事件和方法
  18. Zoie中文文档及简单解析
  19. linux meta 18.0.1 系统安装nodejs
  20. [转]使用TeamCity对项目进行可持续集成管理(一)

热门文章

  1. 用cmd运行java可以javac不行(win10)
  2. centos7如何修改IP地址
  3. React 学习笔记(3) B站视频总结1
  4. 自定义spark UDAF
  5. Atom :奥特曼的使用
  6. 【Android】家庭记账本手机版开发报告七
  7. 常见的http错误
  8. MFC 屏蔽esc跟enter键
  9. MFC双缓冲
  10. HDU_1059 多重背包问题