博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
day4-装饰器前奏
阅读量:5898 次
发布时间:2019-06-19

本文共 2302 字,大约阅读时间需要 7 分钟。

一、定义

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

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

二、原则

  1. 不能修改被装饰函数的源代码
  2. 不能修改被装饰函数的调用方式

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

def logging():    print("logging...")#正确写法,没有修改源码def test1():     pass#错误写法,不能修改源码def test1():    pass    logging()# 调用方式,也不能被修改test1()

三、实现装饰器知识储备

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

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

四、函数即变量

1、python的内存机制

#变量x = 1#函数def test():    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函数之后定义

#bar函数在foo函数之后定义def foo():    print("in the foo")    bar()def bar():    print("in the bar")foo()#输出in the fooin the bar

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

# bar函数是在foo函数之前定义def bar():    print("in the bar")def foo():    print("in the foo")    bar()foo()#输出in the fooin the bar

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

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

# bar函数在foo函数调用之后声明def foo():    print("in the foo")    bar()foo()def bar():    print("in the bar")#输出Traceback (most recent call last):in the foo  File "D:/PycharmProjects/pyhomework/day4/装饰器/函数即变量.py", line 31, in 
foo() File "D:/PycharmProjects/pyhomework/day4/装饰器/函数即变量.py", line 29, in foo bar()NameError: name 'bar' is not defined #bar函数没有定义

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

 

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

五、高阶函数

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

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

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

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

def bar():    time.sleep(3)    print("in the bar")def test1(func):    print(func)    start_time = time.time()    func()    stop_time = time.time()    print("the func run the is %s"%(stop_time-start_time))#没有修改bar的代码test1(bar)  #把bar函数名当做实参传到test1中#输出
#bar函数的内存地址in the barthe func run the is 2.9912972450256348

2、返回值中包括函数名

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

import  timedef bar():    time.sleep(3)    print("in the bar")def test2(func):    print(func)     return func   #返回函数的内存地址#调用test2函数bar = test2(bar)  bar()  #没有bar函数改变调用方式#输出
#打印bar函数的内存地址in the bar

 

转载于:https://www.cnblogs.com/zhangqigao/articles/6543578.html

你可能感兴趣的文章
关于eclipse的ADT(插件)对xml的android:text属性检查修改
查看>>
iostat命令学习
查看>>
SQL 三种分页方式
查看>>
查看linux是ubuntu还是centos
查看>>
html video的url更新,自动清缓存
查看>>
IOS Xib使用——为控制器添加Xib文件
查看>>
CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙步骤
查看>>
react 取消 eslint
查看>>
【11】ajax请求后台接口数据与返回值处理js写法
查看>>
Python菜鸟之路:Jquery Ajax的使用
查看>>
LeetCode算法题-Maximum Depth of Binary Tree
查看>>
sha1withRSA算法
查看>>
Vim和操作系统剪贴板交互
查看>>
Cox 教学视频5
查看>>
JVM类加载(4)—加载器
查看>>
public/private/protected的具体区别
查看>>
面试宝典——求一个字符串中连续出现次数最多的子串
查看>>
VMware Workstation虚拟机上网设置
查看>>
Jenkins持续集成学习-搭建jenkins问题汇总
查看>>
C#Note13:如何在C#中调用python
查看>>