python中的闭包和装饰器

一、闭包

  1.1闭包的定义

      在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。

  1.2闭包的构成条件

 

     (1)函数嵌套

 

     (2)内部函数使用了外部函数的变量或者外部函数的参数

 

     (3)外部函数返回了内部函数

简单的实例:

 

 1 # 外部函数
 2 def fun_out(a):
 3     # 内部函数
 4     def fun_inner(b):
 5         result = a + b
 6         print(result)
 7 
 8     # 外部函数返回了内部函数,这里返回的内部函数就是闭包
 9     return fun_inner
10 
11 # 创建闭包实例    
12 function = fun_out(1)
13 function(2)
》3 

  1.3、如何修改闭包内使用的外部函数的变量

    想要在内部函数修改外部函数的变量或者是参数需要在内部函数中用nonlocal关键字声明外部函数的变量或者是参数。     

   1 #外部函数 
   2 def fun_out():
   3     num1 = 5
   4     #内部函数
   5     def fun_inner(num2) :
   6         #使用nonlocal关键字声明外部函数的变量
   7         nonlocal num1
   8         num1=20
   9         #内部函数使用了外部函数的参数num1
  10         result=num1+num2
  11         print("sum:"result)
  12     return fun_inner                                                                                    

    闭包可以保存外部函数内的变量,不会随着外部函数调用完而销毁。

 

 

注意点:

 

  • 由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,消耗内存。

 

 

二、装饰器

  2.1、装饰器的定义

      装饰器就是给已经存在的函数添加额外功能函数,它本质上就是一个闭包函数

   2.2、装饰器的特点

      (1) 不修改已经存在的函数

       (2) 不修改已经存在的函数调用方式

       (3) 给已经存在的函数添加额外的功能 

   2.3、实例代码

 

 1 # 添加一个登录验证的功能
 2 def check(fun):
 3     def inner():
 4         print("请先登录....")
 5         fun()
 6 return inner
 7 
 8 def comment():
 9     print("发表评论")
10 
11 
12 # 使用装饰器来装饰函数
13 comment = check(comment)
14 comment()    

 

   注意点:

  2.4、装饰器的语法糖写法

    Python给提供了一个装饰函数更加简单的写法,那就是语法糖,语法糖的书写格式是: @装饰器名字,通过语法糖的方式也可以完成对已有函数的装饰。

 

 # 添加一个登录验证的功能
 def check(fun):
     def inner():
         print("请先登录....")
         fun()
 return inner

 # 使用语法糖来装饰函数
 @check
 def comment():
     print("发表评论") 
 
 comment()  

    注意:

      • @check 等价于 comment = check(comment)
      • 装饰器的执行时间是加载模块时立即执行。

  2.5、多个装饰器的使用

1 @test2
2 @test1
3 def index():
4     return "BLUE"
5 
6 #装饰过程index = test1(test2(index))
7 #多个装饰器可以对函数进行多个功能的装饰,装饰顺序是由内到外的进行装饰

  2.6、带有参数的装饰器

    带有参数的装饰器就是使用装饰器装饰函数的时候可以传入指定参数,语法格式: @装饰器(参数,...)

 1 # 添加输出日志的功能
 2 def logging(flag):
 3 
 4     def decorator(fn):
 5         def inner(num1, num2):
 6             if flag == "+":
 7                 print("--正在努力加法计算--")
 8             elif flag == "-":
 9                 print("--正在努力减法计算--")
10             result = fn(num1, num2)
11             return result
12         return inner
13 
14     # 返回装饰器
15     return decorator
16 
17 
18 # 使用装饰器装饰函数
19 @logging("+")
20 def add(a, b):
21     result = a + b
22     return result
23 
24 
25 @logging("-")
26 def sub(a, b):
27     result = a - b
28     return result
29 
30 result = add(1, 2)
31 print(result)
32 
33 result = sub(1, 2)
34 print(result)

 

   注意:

  • 装饰器只能接收一个参数,并且还是函数类型。

类装饰器

  装饰器还有一种特殊的用法就是类装饰器,就是通过定义一个类来装饰函数

 

 1 class Check(object):
 2     def __init__(self, fn):
 3         # 初始化操作在此完成
 4         self.__fn = fn
 5 
 6     # 实现__call__方法,表示对象是一个调用对象,可以像调用函数一样进行调用。
 7     def __call__(self, *args, **kwargs):
 8         # 添加装饰功能
 9         print("请先登陆...")
10         self.__fn()
11 
12 
13 @Check
14 def comment():
15     print("发表评论")
16 
17 
18 comment()

 

    

 

      

 


 

 

                                                                                                                                                                                                                                   

相关文章

功能概要:(目前已实现功能)公共展示部分:1.网站首页展示...
大体上把Python中的数据类型分为如下几类: Number(数字) ...
开发之前第一步,就是构造整个的项目结构。这就好比作一幅画...
源码编译方式安装Apache首先下载Apache源码压缩包,地址为ht...
前面说完了此项目的创建及数据模型设计的过程。如果未看过,...
python中常用的写爬虫的库有urllib2、requests,对于大多数比...