转自小马哥:

闭包和装饰器充分体现了Python语法糖的优雅感觉。

在本文中,我们的实验要完成两个工作,一个是加法,一个是累计调用加法的次数,最普通的Python程序可以这么写:

 def validate(a, b):
if ((isinstance(a, int) or isinstance(a, float))
and (isinstance(b, int) or isinstance(b, float))):
return True
return False def add(a, b):
if validate(a, b):
return a + b
return "Invalid." count = 0 def counter(func):
global count
count = count + 1
return (count, func) print(counter(add(1, 2)))
print(counter(add(1, 3)))
print(counter(add('', 4)))
print(counter(add(1, 5)))
print(counter(add(1, 6)))

结果:

>> long@happytime:~/development/closure$ python3 test.py
>> (, )
>> (, )
>> (, 'Invalid.')
>> (, )
>> (, )

虽然可以正确显示结果,但是有如下几个不满意的地方:

  1. 全局变量的使用首先是不提倡的;
  2. 每次调用add都需要手动调用counter;
  3. add函数和validate函数耦合在一起,如果以后需要判断更多条件,会产生很多层的if-else的嵌套。

用闭包解决问题1:

 def validate(a, b):
if ((isinstance(a, int) or isinstance(a, float))
and (isinstance(b, int) or isinstance(b, float))):
return True
return False def add(a, b):
if validate(a, b):
return a + b
return "Invalid." def counter():
ct = 0 def do(func):
nonlocal ct
ct = ct + 1
return (ct, func)
return do ct = counter()
print(ct(add(1, 2)))
print(ct(add(1, 3)))
print(ct(add('', 4)))
print(ct(add(1, 5)))
print(ct(add(1, 6)))

结果:

>> long@happytime:~/development/closure$ python3 test1.py
>> (, )
>> (, )
>> (, 'Invalid.')
>> (, )
>> (, )

用装饰器进一步解决问题2:

 def validate(a, b):
if ((isinstance(a, int) or isinstance(a, float))
and (isinstance(b, int) or isinstance(b, float))):
return True
return False def counter(func):
ct = 0 def count(a, b):
nonlocal ct
ct = ct + 1
return (ct, func(a, b))
return count @counter
def add(a, b):
if validate(a, b):
return a + b
return "Invalid." print(add(1, 2))
print(add(1, 3))
print(add('', 4))
print(add(1, 5))
print(add(1, 6))

结果:

>> long@happytime:~/development/closure$ python3 test2.py
>> (1, 3)
>> (2, 4)
>> (3, 'Invalid.')
>> (4, 6)
>> (5, 7)

用装饰器进一步解决问题3:

 def validate(func):
def do(a, b):
if ((isinstance(a, int) or isinstance(a, float))
and (isinstance(b, int) or isinstance(b, float))):
return func(a, b)
return "Invalid."
return do def counter(func):
ct = 0 def count(a, b):
nonlocal ct
ct = ct + 1
return (ct, func(a, b))
return count @counter
@validate
def add(a, b):
return a + b print(add(1, 2))
print(add(1, 3))
print(add('', 4))
print(add(1, 5))
print(add(1, 6))

结果:

>> long@happytime:~/development/closure$ python3 test3.py
>> (1, 3)
>> (2, 4)
>> (3, 'Invalid.')
>> (4, 6)
>> (5, 7)

运用装饰器,可以在执行add的同时做很多事情,但耦合度很低,需要就加上装饰器,不需要就去掉。不过需要注意的是,多个装饰器的调用顺序是从下到上。所以@validate在@counter的下面。

python闭包与装饰器的更多相关文章

  1. python 闭包和装饰器

    python 闭包和装饰器 一.闭包闭包:外部函数FunOut()里面包含一个内部函数FunIn(),并且外部函数返回内部函数的对象FunIn,内部函数存在对外部函数的变量的引用.那么这个内部函数Fu ...

  2. 高逼格利器之Python闭包与装饰器

    生活在魔都的小明,终于攒够了首付,在魔都郊区买了一套房子:有一天,小明踩了狗屎,中了一注彩票,得到了20w,小明很是欢喜,于是想干脆用这20万来装修房子吧(decoration): 整个装修过程,小明 ...

  3. Python—闭包和装饰器

    闭包 定义:内部函数对外部函数变量的引用,则将该函数与用到的变量称为闭包. 闭包必须满足以下三个条件: 必须有一个内嵌函数. 内嵌函数必须引用外部函数中的变量. 外部函数返回值必须是内嵌函数的引用. ...

  4. Python 简明教程 --- 22,Python 闭包与装饰器

    微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 当你选择了一种语言,意味着你还选择了一组技术.一个社区. 目录 本节我们来介绍闭包与装饰器. 闭包与 ...

  5. Python闭包及装饰器

    Python闭包 先看一个例子: def outer(x): def inner(y): return x+y return innder add = outer(8) print add(6) 我们 ...

  6. python闭包以及装饰器

    通俗的定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).它只不过是个“内层”的函数,由一个名字(变量)来指代,而这个名字(变 ...

  7. python闭包和装饰器

    本文目录: 1. 闭包的解析和用法 2. 函数式装饰器 3. 类装饰器 一.闭包 闭包是一种函数,从形式上来说是函数内部定义(嵌套)函数,实现函数的扩展.在开发过程中,考虑到兼容性和耦合度问题,如果想 ...

  8. python闭包和装饰器(转)

    一.python闭包 1.内嵌函数 >>> def func1(): ... print ('func1 running...') ... def func2(): ... prin ...

  9. 详解Python闭包,装饰器及类装饰器

    在项目开发中,总会遇到在原代码的基础上添加额外的功能模块,原有的代码也许是很久以前所写,为了添加新功能的代码块,您一般还得重新熟悉源代码,稍微搞清楚一点它的逻辑,这无疑是一件特别头疼的事情.今天我们介 ...

随机推荐

  1. 调用c++接口类

    调用c++接口类 public class CarDeviceDll { /*对dll库进行一些初始化*/ [DllImport("IDI.dll")] public static ...

  2. 未将对象引用设置到对象的实例 启用 JIT 调试后,任何无法处理的异常

    严谨!!!! DataSet ds = salarySum.GetDataSalarySum2(libUser.SelectedValue, dtpMonth.Value.Date);         ...

  3. HDU 5752 Sqrt Bo (思维题) 2016杭电多校联合第三场

    题目:传送门. 题意:一个很大的数n,最多开5次根号,问开几次根号可以得到1,如果5次还不能得到1就输出TAT. 题解:打表题,x1=1,x2=(x1+1)*(x1+1)-1,以此类推.x5是不超过l ...

  4. September 24th 2016 Week 39th Saturday

    The worst solitude is to be destitute of sincere friendship. 最大的孤独莫过于没有真诚的友谊. I walk slowly, but I n ...

  5. Linux iostat字段解析

    iostat主要用于监控系统设备的IO负载情况,iostat首次运行时显示自系统启动开始的各项统计信息,之后运行iostat将显示自上次运行该命令以后的统计信息.用户可以通过指定统计的次数和时间来获得 ...

  6. spring AOP 的几种实现方式(能测试)

    我们经常会用到的有如下几种 1.基于代理的AOP 2.纯简单Java对象切面 3.@Aspect注解形式的 4.注入形式的Aspcet切面 一.需要的java文件 public class ChenL ...

  7. Vs 控件错位 右侧资源管理器文件夹点击也不管用,显示异常

    问题:显卡驱动异常. 缘由:驱动精灵万能显卡安装系统 解决方案:根据笔记本型号去官网下载适配显卡驱动.

  8. ASP.NET Web Api 安全性(转载)

    转载地址:http://www.cnblogs.com/fzrain/p/3552423.html 在Web Api中强制使用Https 我们可以在IIS级别配置整个Web Api来强制使用Https ...

  9. 【JAVA正则表达式综合练习】

    一.治疗口吃. 将字符串“我我我我我我我..........我.......要要要要要..................要要要要...学习习习习.......习习习习习习习习编程程程程程程..... ...

  10. sdut 2498【aoe 网上的关键路径】

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2498 代码超时怎么破: #include< ...