装饰器前奏

一、定义

1、装饰器:本质是函数。

2、功能:用来装饰其他函数,顾名思义就是,为其他的函数添加附件功能的。

二、原则

1、不能修改被装饰函数的源代码

2、不能修改被装饰函数的调用方式

装饰器为什么会有这两个原则呐?因为如果你写的这个程序在生产环境下已经运行了,如果修改别人的源代码或者修改别人的调用方式,那么出了问题,后果可想而知,所以我们要牢记上面两个原则。

三、实现装饰器知识储备

  1. 函数即"变量"
  2. 高阶函数
  3. 嵌套函数

最终: 高阶函数+嵌套函数 => 装饰器

四、函数即变量

1、python的内存机制

1 #变量
2 x = 1
3 #函数
4 def test():
5     pass

以上一个变量一个函数在内存中的表现形式如下图:

在python解释器中,有一个概念叫做引用基数,那什么叫引用基数呐,就是比方说,x=1,它会先在内存当中把1这个值试试在在的存放下来,这个x其实就是1的门牌号,也是对1的一次引用。python什么时候把这个1这个屋子清空呐?它会等到1所对应的门牌号都没有了,就会把1这里面的东西给清掉,这个也是python的内存回收机制,就是靠这种方式回收的。

2、del清理

那我们用什么清理呐?用del去清理门牌号,就是对1的值引用的变量,del  x就表示清理掉1对应的x的门派号。如果x没有被del,则x永远不还被删除,除非程序结束了,不然永远不会被删除。del删除的不是1,只是把门牌号x删除了,只是定期刷新时,发现1没有被其他门牌号引用了,才会被清掉。

3、函数在内存的表现形式

我们先通过三个例子来解释一下:

①bar函数在foo函数之后定义

 1 #bar函数在foo函数之后定义
 2 def foo():
 3     print("in the foo")
 4     bar()
 5
 6 def bar():
 7     print("in the bar")
 8
 9 foo()
10
11 #输出
12 in the foo
13 in the bar

②bar函数是在foo函数之前定义

 1 # bar函数是在foo函数之前定义
 2 def bar():
 3     print("in the bar")
 4
 5 def foo():
 6     print("in the foo")
 7     bar()
 8
 9 foo()
10
11 #输出
12 in the foo
13 in the bar

显然,两种写法效果是一样的,那我们来看看第三种情况。

③bar函数在foo函数调用之后声明

 1 # bar函数在foo函数调用之后声明
 2 def foo():
 3     print("in the foo")
 4     bar()
 5
 6 foo()
 7
 8 def bar():
 9     print("in the bar")
10
11 #输出
12 Traceback (most recent call last):
13 in the foo
14   File "D:/PycharmProjects/pyhomework/day4/装饰器/函数即变量.py", line 31, in <module>
15     foo()
16   File "D:/PycharmProjects/pyhomework/day4/装饰器/函数即变量.py", line 29, in foo
17     bar()
18 NameError: name ‘bar‘ is not defined  #bar函数没有定义

为啥呢?bar函数我不是定义了吗?下面我们就用一个图来解释一下。

从图中不难看出第三种错误是因为在执行foo函数时,当调用bar函数时,bar还函数还定义,所以报错。

五、高阶函数

实现高阶函数有两个条件:

  1. 把一个函数名当做实参传给另外一个函数
  2. 返回值中包含函数名

1、把一个函数名当做实参传给另外一个函数

作用:在不修改被装饰函数源代码的情况下为其添加功能

 1 def bar():
 2     time.sleep(3)
 3     print("in the bar")
 4
 5 def test1(func):
 6     print(func)
 7     start_time = time.time()
 8     func()
 9     stop_time = time.time()
10     print("the func run the is %s"%(stop_time-start_time))
11 #没有修改bar的代码
12 test1(bar)  #把bar函数名当做实参传到test1中
13
14 #输出
15 <function bar at 0x0000000000A7D378>  #bar函数的内存地址
16 in the bar
17 the func run the is 2.9912972450256348

2、返回值中包括函数名

作用:不修改函数调用方式

 1 import  time
 2
 3 def bar():
 4     time.sleep(3)
 5     print("in the bar")
 6
 7 def test2(func):
 8     print(func)
 9     return func   #返回函数的内存地址
10
11 #调用test2函数
12 bar = test2(bar)
13 bar()  #没有bar函数改变调用方式
14
15 #输出
16 <function bar at 0x0000000000B6D378>  #打印bar函数的内存地址
17 in the bar
时间: 2024-10-03 14:01:59

装饰器前奏的相关文章

装饰器前奏(2017年8月20日 21:10:27)

实现装饰器知识储备 1.函数即"变量" 2.高阶函数 3.嵌套函数 # author :Yeison.Z import time def timmer(func): def warpper(*args,**kwargs): start_time=time.time() func() stop_time=time.time() print('the func run time is %s' %(stop_time-start_time)) return warpper @timmer d

Python学习之路:装饰器前奏

装饰器: 定义:本质是函数,功能:(装饰其他函数)就是为其他函数添加附加功能: 原则:1.不能修改被装饰函数的源代码 2.不能修改被装饰的函数的调用方式 实现装饰器知识储备: 1.函数即"变量" 2.高阶函数 3.嵌套函数 高阶函数+嵌套函数 =>装饰器 import time def timer(func): def warper(*args,**kwargs): start_time =time.time() func() stop_time=time.time() prin

装饰器复习

装饰器前奏: 装饰器变形: (1)第一种变形 (2)第二种变形 (3)第三种变形 (4)第四种变形(正确且标准得装饰器) 装饰器装饰带有参数的函数: 带标志位的装饰器: 应用场景:例如装饰器是为了测试代码运行时间,但是生产环境上线是需要去掉多余得功能,这时候可以把装饰器标志位改为False即可,避免了频繁的删除操作. 带参数的装饰器: import time current_login = {'name': None, 'login': False} def timmer(func): def

装饰器、生成器、迭代器

装饰器的前奏 装饰器:本质是函数 功能:就是装饰成其他函数  就是为其他函数添加附加功能的 高阶函数+嵌套函数=装饰器 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 总结一句话:装饰器对被装饰的函数是完全透明的 实现装饰器的只是储备: 1.函数名即"变量"   将函数体赋值给变量   和内存回收机制一样 2.高阶函数 2.1.把函数名作为实参传递给形参(可返回被修饰函数的地址)(不修改源代码的情况可添加新的功能) 2.2返回值中包含函数地址(不修改函数的调

一篇文章让你明白python的装饰器

在看闭包问题之前先来看看关于python中作用域的问题 变量作用域 对于上述代码中出现错误,肯定没什么疑问了,毕竟b并没有定义和赋值,当我们把代码更改如下后: 再看一个例子: 首先这个错误已经非常明显:说在赋值之前引用了局部变量b 可能很多人觉得会打印10然后打印6,其实这里就是涉及到变量作用域的问题当Python编译函数的的定义体的时候,它判断b是局部变量,毕竟在函数中有b = 9表示给b赋值了,所以python会从本地环境获取b,当我们调用方法执行的时候,定义体会获取并打印变量a的值,但是当

Day4 - 迭代器&amp;生成器、装饰器、Json &amp; pickle 数据序列化、软件目录结构规范

---恢复内容开始--- 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 需求:列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值加1 1 a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 b = [] 3 for i in a: 4 b.append(i+1) 5 a = b 6 print(a) 普通青

python3 装饰器

看廖雪峰官网的python3装饰器有感 装饰器即将一个函数作为变量在新的函数中调用此函数. 作业: 能否写出一个@log的decorator,使它既支持: @logdef f():     pass 又支持: @log('execute')def f():     pass      例1: import functools import time def log(*args,**kwargs):     # *args 是个元组     if args and isinstance(args,

day14 带函数的装饰器、多个装饰器装饰一个函数

一.带参数的装饰器:------开关 __author__ = 'Administrator' F=True def outer(F): def wap(fun):#gg def inner(*args,**kwargs): if F: print("inner before") ret=fun(*args,**kwargs)#gg() print("inner after") else: ret=fun(*args,**kwargs) return ret ret

Python 装饰器

一.定义 器即函数 装饰即修饰,意指为其他函数添加新功能 装饰器本身可以是任意可调用对象,被装饰的对象本身也可以是任意可调用对象 实现装饰器: 装饰器=高阶函数+函数嵌套+闭包 二.原则: 1 .开放封闭原则:对扩展是开放的,对修改是封闭 2.1 装饰器的遵循的原则:1 不修改被装饰对象的源代码 2 不修改被调用对象的调用方式 三.目的 装饰器的目的是:在遵循1和2原则的前提,为其他新功能函数添加 四.定义位置 @装饰器名,必须写在被装饰对象的正上方,并且是单独一行 import time de