zoukankan      html  css  js  c++  java
  • python闭包与装饰器

    转自小马哥:

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

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

     1 def validate(a, b):
     2     if ((isinstance(a, int) or isinstance(a, float))
     3             and (isinstance(b, int) or isinstance(b, float))):
     4         return True
     5     return False
     6 
     7 
     8 def add(a, b):
     9     if validate(a, b):
    10         return a + b
    11     return "Invalid."
    12 
    13 
    14 count = 0
    15 
    16 
    17 def counter(func):
    18     global count
    19     count = count + 1
    20     return (count, func)
    21 
    22 print(counter(add(1, 2)))
    23 print(counter(add(1, 3)))
    24 print(counter(add('1', 4)))
    25 print(counter(add(1, 5)))
    26 print(counter(add(1, 6)))

    结果:

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

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

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

    用闭包解决问题1:

     1 def validate(a, b):
     2     if ((isinstance(a, int) or isinstance(a, float))
     3             and (isinstance(b, int) or isinstance(b, float))):
     4         return True
     5     return False
     6 
     7 
     8 def add(a, b):
     9     if validate(a, b):
    10         return a + b
    11     return "Invalid."
    12 
    13 
    14 def counter():
    15     ct = 0
    16 
    17     def do(func):
    18         nonlocal ct
    19         ct = ct + 1
    20         return (ct, func)
    21     return do
    22 
    23 
    24 ct = counter()
    25 print(ct(add(1, 2)))
    26 print(ct(add(1, 3)))
    27 print(ct(add('1', 4)))
    28 print(ct(add(1, 5)))
    29 print(ct(add(1, 6)))

    结果:

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

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

     1 def validate(a, b):
     2     if ((isinstance(a, int) or isinstance(a, float))
     3             and (isinstance(b, int) or isinstance(b, float))):
     4         return True
     5     return False
     6 
     7 
     8 def counter(func):
     9     ct = 0
    10 
    11     def count(a, b):
    12         nonlocal ct
    13         ct = ct + 1
    14         return (ct, func(a, b))
    15     return count
    16 
    17 
    18 @counter
    19 def add(a, b):
    20     if validate(a, b):
    21         return a + b
    22     return "Invalid."
    23 
    24 
    25 print(add(1, 2))
    26 print(add(1, 3))
    27 print(add('1', 4))
    28 print(add(1, 5))
    29 print(add(1, 6))

    结果:

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

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

     1 def validate(func):
     2     def do(a, b):
     3         if ((isinstance(a, int) or isinstance(a, float))
     4                 and (isinstance(b, int) or isinstance(b, float))):
     5             return func(a, b)
     6         return "Invalid."
     7     return do
     8 
     9 
    10 def counter(func):
    11     ct = 0
    12 
    13     def count(a, b):
    14         nonlocal ct
    15         ct = ct + 1
    16         return (ct, func(a, b))
    17     return count
    18 
    19 
    20 @counter
    21 @validate
    22 def add(a, b):
    23     return a + b
    24 
    25 
    26 print(add(1, 2))
    27 print(add(1, 3))
    28 print(add('1', 4))
    29 print(add(1, 5))
    30 print(add(1, 6))

    结果:

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

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

    努力吧,为了媳妇儿,为了家。。。
  • 相关阅读:
    转:spring-session
    转:SpringBoot项目如何进行打包部署
    事务的隔离级别
    获取打卡记录接口返回数据情况说明
    批注@SuppressWarnings 的作用
    mybatis-generator eclipse插件 使用方法
    几种常见数据库的driverClassName和url
    ssm 配置多个数据源
    常用正则表达式
    tomcat 配置成服务
  • 原文地址:https://www.cnblogs.com/jlj9520/p/5043339.html
Copyright © 2011-2022 走看看