转自小马哥:

闭包和装饰器充分体现了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. IOS-MVC的使用

    1.Model不允许和Controller,View打交道.也就是Model根本不知道谁会用自己,Model中不能有任何对 Controller和View的引用.正所谓:Don't call me, ...

  2. 如何将.il、.res文件封装成dll文件

    将你的.il..res文件保存在你的硬盘上,如下图: 我存放的路径在E盘的test文件夹中,我们开始封装了咯.进入DOS命令,如下图: 我们通过DOS命令先进入.il..res文件目录,如下图: 然后 ...

  3. yii和php的一些细节

    yii   index.php ini_set("display_errors", 1); iconv这个函数不能直接用 需要检测!!! function gb2312_utf8( ...

  4. AutoLayout 图解各种约束

  5. 【2016-09-16】UbuntuServer14.04或更高版本安装问题记录

    出于项目需要,我们的Qt程序需要运行在 1. Windows/Linux-X86平台(CPU为常见的桌面级CPU如G3220.I3等): 2. Windows/Linux-X86低功耗平台(CPU为I ...

  6. Mysql复制语句

    可分为三组(Group):用于Master ,用于Slave,用于任何复制服务.

  7. Android错误:Re-installation failed due to different application signatures

    Re-installation failed due to different application signatures (2013-04-20 14:27:32) 转载▼ 标签: 解决方法 问题 ...

  8. logstash之multiline插件,匹配多行日志

    在外理日志时,除了访问日志外,还要处理运行时日志,该日志大都用程序写的,比如log4j.运行时日志跟访问日志最大的不同是,运行时日志是多行,也就是说,连续的多行才能表达一个意思. 在filter中,加 ...

  9. OCJP(1Z0-851) 模拟题分析(二)over

    Exam : 1Z0-851 Java Standard Edition 6 Programmer Certified Professional Exam 以下分析全都是我自己分析或者参考网上的,定有 ...

  10. 攻城狮在路上(叁)Linux(十四)--- 查阅文件内容

    常用命令:cat.tac.nl.more.less.head.tail.od... 一.直接查看文件内容:cat.tac.nl <==一次性全部读取 1.cat [-AbEnTv] 文件名 参数 ...