转自小马哥:

闭包和装饰器充分体现了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. 【python】lxml

    来源:http://lxml.de/tutorial.html lxml是python中处理xml的一个非常强大的库,可以非常方便的解析和生成xml文件.下面的内容翻译了链接中的一部分 1.生成空xm ...

  2. Ajax如何使用Session

    在Ajax中有时会使用到Session,在aspx.cs文件这样获取: string name = Session["name"]; 但是在Ajax中就不能这样获取Session, ...

  3. 118. Pascal's Triangle

    题目: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5, ...

  4. checkbox实现全选全不选

    1.jQuery实现checkbox全选全不选 <!DOCTYPE html> <head runat="server"> <title>jQu ...

  5. [Android Rro] SDK JAR

    cd ../../../outputs/aar/mkdir AAR_VERSIONmkdir JAR_VERSIONmv app-release.aar AAR_VERSION/${project_n ...

  6. CSS3的新属性的一下总结

    阮一峰:http://www.ruanyifeng.com/blog/2014/02/css_transition_and_animation.html 由于自己经常搞混:animation,tran ...

  7. Redis自定义动态字符串(sds)模块(二)

    sds模块的具体实现: 1.sdsnewlen 根据参数生成一个sds字符串 sds sdsnewlen(const void *init, size_t initlen) { struct sdsh ...

  8. NYOJ题目98成绩转换

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsQAAAJhCAIAAADJ5jGJAAAgAElEQVR4nO3dq3LkSPg36O8mzH0hxn ...

  9. VS对路径的访问被拒绝

    问题:权限问题. 1.检查自己电脑账户.是否是Administrator.如果没有启用.在[我的电脑]——[管理]——[本地用户和组]——[用户]——[Administrator]——[属性启用] 2 ...

  10. C# 中的Singleton模式

    一般写Singleton基本都是一下这个套路 class Singleton { public static Singleton instance; private Singleton() { } p ...