python学习笔记7:装B神器之装饰器

参考:http://www.cnblogs.com/wupeiqi/articles/4980620.html

1、必备


1

2

3

4

5

6

7

8

9

10

11

12

13

14

#### 第一波 ####

def foo():

    print ‘foo‘

foo     #表示是函数

foo()   #表示执行foo函数

#### 第二波 ####

def foo():

    print ‘foo‘

foo = lambda x: x + 1

foo()   # 执行下面的lambda表达式,而不再是原来的foo函数,因为函数 foo 被重新定义了

2、需求来了

初创公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作、redis调用、监控API等功能。业务部门使用基础功能时,只需调用基础平台提供的功能即可。如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

############### 基础平台提供的功能如下 ###############

def f1():

    print ‘f1‘

def f2():

    print ‘f2‘

def f3():

    print ‘f3‘

def f4():

    print ‘f4‘

############### 业务部门A 调用基础平台提供的功能 ###############

f1()

f2()

f3()

f4()

############### 业务部门B 调用基础平台提供的功能 ###############

f1()

f2()

f3()

f4()

目前公司有条不紊的进行着,但是,以前基础平台的开发人员在写代码时候没有关注验证相关的问题,即:基础平台的提供的功能可以被任何人使用。现在需要对基础平台的所有功能进行重构,为平台提供的所有功能添加验证机制,即:执行功能前,先进行验证。

老大把工作交给 Low B,他是这么做的:


1

跟每个业务部门交涉,每个业务部门自己写代码,调用基础平台的功能之前先验证。诶,这样一来基础平台就不需要做任何修改了。

当天Low B 被开除了...

老大把工作交给 Low BB,他是这么做的:


1

只对基础平台的代码进行重构,让N业务部门无需做任何修改

 1 ############### 基础平台提供的功能如下 ###############
 2
 3 def f1():
 4     # 验证1
 5     # 验证2
 6     # 验证3
 7     print ‘f1‘
 8
 9 def f2():
10     # 验证1
11     # 验证2
12     # 验证3
13     print ‘f2‘
14
15 def f3():
16     # 验证1
17     # 验证2
18     # 验证3
19     print ‘f3‘
20
21 def f4():
22     # 验证1
23     # 验证2
24     # 验证3
25     print ‘f4‘
26
27 ############### 业务部门不变 ###############
28 ### 业务部门A 调用基础平台提供的功能###
29
30 f1()
31 f2()
32 f3()
33 f4()
34
35 ### 业务部门B 调用基础平台提供的功能 ###
36
37 f1()
38 f2()
39 f3()
40 f4()

过了一周 Low BB 被开除了...

老大把工作交给 Low BBB,他是这么做的:


1

只对基础平台的代码进行重构,其他业务部门无需做任何修改

 1 ############### 基础平台提供的功能如下 ###############
 2
 3 def check_login():
 4     # 验证1
 5     # 验证2
 6     # 验证3
 7     pass
 8
 9
10 def f1():
11
12     check_login()
13
14     print ‘f1‘
15
16 def f2():
17
18     check_login()
19
20     print ‘f2‘
21
22 def f3():
23
24     check_login()
25
26     print ‘f3‘
27
28 def f4():
29
30     check_login()
31
32     print ‘f4‘

老大看了下Low BBB 的实现,嘴角漏出了一丝的欣慰的笑,语重心长的跟Low BBB聊了个天:

老大说:

写代码要遵循开发封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:

  • 封闭:已实现的功能代码块
  • 开放:对扩展开发

如果将开放封闭原则应用在上述需求中,那么就不允许在函数 f1 、f2、f3、f4的内部进行修改代码,老板就给了Low BBB一个实现方案:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

def w1(func):

    def inner():

        # 验证1

        # 验证2

        # 验证3

        return func()

    return inner

@w1

def f1():

    print ‘f1‘

@w1

def f2():

    print ‘f2‘

@w1

def f3():

    print ‘f3‘

@w1

def f4():

    print ‘f4‘

对于上述代码,也是仅仅对基础平台的代码进行修改,就可以实现在其他人调用函数 f1 f2 f3 f4 之前都进行【验证】操作,并且其他业务部门无需做任何操作。

Low BBB心惊胆战的问了下,这段代码的内部执行原理是什么呢?

老大正要生气,突然Low BBB的手机掉到地上,恰恰屏保就是Low BBB的女友照片,老大一看一紧一抖,喜笑颜开,交定了Low BBB这个朋友。详细的开始讲解了:

单独以f1为例:


1

2

3

4

5

6

7

8

9

10

11

def w1(func):

    def inner():

        # 验证1

        # 验证2

        # 验证3

        return func()

    return inner

@w1

def f1():

    print ‘f1‘

当写完这段代码后(函数未被执行、未被执行、未被执行),python解释器就会从上到下解释代码,步骤如下:

  1. def w1(func):  ==>将w1函数加载到内存
  2. @w1

没错,从表面上看解释器仅仅会解释这两句代码,因为函数在没有被调用之前其内部代码不会被执行。

从表面上看解释器着实会执行这两句,但是 @w1 这一句代码里却有大文章,@函数名 是python的一种语法糖。

如上例@w1内部会执行一下操作:

  • 执行w1函数,并将 @w1 下面的 函数 作为w1函数的参数,即:@w1 等价于 w1(f1)
    所以,内部就会去执行:
        def inner:
            #验证
            return f1()   # func是参数,此时 func 等于 f1
        return inner     # 返回的 inner,inner代表的是函数,非执行函数
    其实就是将原来的 f1 函数塞进另外一个函数中
  • 将执行完的 w1 函数返回值赋值给@w1下面的函数的函数名
    w1函数的返回值是:
       def inner:
            #验证
            return 原来f1()  # 此处的 f1 表示原来的f1函数
    然后,将此返回值再重新赋值给 f1,即:
    新f1 = def inner:
                #验证
                return 原来f1() 
    所以,以后业务部门想要执行 f1 函数时,就会执行 新f1 函数,在 新f1 函数内部先执行验证,再执行原来的f1函数,然后将 原来f1 函数的返回值 返回给了业务调用者。
    如此一来, 即执行了验证的功能,又执行了原来f1函数的内容,并将原f1函数返回值 返回给业务调用着

3、参数、多装饰器

参数:

def w1(func):
    def inner(arg):
        # 验证1
        # 验证2
        # 验证3
        return func(arg)
    return inner

@w1
def f1(arg):
    print ‘f1‘

一个参数

 1 def w1(func):
 2     def inner(arg1,arg2):
 3         # 验证1
 4         # 验证2
 5         # 验证3
 6         return func(arg1,arg2)
 7     return inner
 8
 9 @w1
10 def f1(arg1,arg2):
11     print ‘f1‘

二个参数

 1 ef w1(func):
 2     def inner(arg1,arg2,arg3):
 3         # 验证1
 4         # 验证2
 5         # 验证3
 6         return func(arg1,arg2,arg3)
 7     return inner
 8
 9 @w1
10 def f1(arg1,arg2,arg3):
11     print ‘f1‘

三个参数

 1 def w1(func):
 2     def inner(*args,**kwargs):
 3         # 验证1
 4         # 验证2
 5         # 验证3
 6         return func(*args,**kwargs)
 7     return inner
 8
 9 @w1
10 def f1(arg1,arg2,arg3):
11     print ‘f1‘

多个参数

多个装饰器装饰使用


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

def w1(func):

    def inner(*args,**kwargs):

        # 验证1

        # 验证2

        # 验证3

        return func(*args,**kwargs)

    return inner

def w2(func):

    def inner(*args,**kwargs):

        # 验证1

        # 验证2

        # 验证3

        return func(*args,**kwargs)

    return inner

@w1

@w2

def f1(arg1,arg2,arg3):

    print ‘f1‘

NB的装饰器使用:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

#!/usr/bin/env python

#coding:utf-8

 

def Before(request,kargs):

    print ‘before‘

     

def After(request,kargs):

    print ‘after‘

 

 

def Filter(before_func,after_func):

    def outer(main_func):

        def wrapper(request,kargs):

             

            before_result = before_func(request,kargs)

            if(before_result != None):

                return before_result;

             

            main_result = main_func(request,kargs)

            if(main_result != None):

                return main_result;

             

            after_result = after_func(request,kargs)

            if(after_result != None):

                return after_result;

             

        return wrapper

    return outer

     

@Filter(Before, After)

def Index(request,kargs):

    print ‘index‘

时间: 2024-08-29 13:06:16

python学习笔记7:装B神器之装饰器的相关文章

python学习笔记-Day05-第一部分(再谈装饰器)(递归)

今天又花了多半天来学习装X利器---装饰器, 来详细的讲讲装饰器的用法 还是要说一下,学装饰器之前要先搞清楚什么是函数.装饰器就是对函数进行一个包装,打个比喻来说就是: 假设有一个箱子A,在箱子A的外面又套了一个大箱子,外面的大箱子还起名叫A,以后在找里面的小箱子A的时候,就先去找外面的大箱子A,打开外面的大箱子A之后 在打开内部的小箱子A,这个就是装饰器. 装饰器也是一个函数,至少两层 def outter(func):               #定义函数 outter,参数为一个函数的函

python day4笔记 常用内置函数与装饰器

1.常用的python函数 abs             求绝对值 all               判断迭代器中所有的数据是否为真或者可迭代数据为空,返回真,否则返回假 any             判断迭代器中的数据是否有一个为真,有返回真,可迭代数据为空或者没有真,返回假 bin             转换整数为二进制字符串 hex            转换整数为十六进制字符串 oct             转换整数为八进制字符串 bool           转换数据为布尔值

python学习之类和实例的属性;装饰器@property

无论是类还是实例,一切皆是对象. Python是强动态语言,和java在这点上有所不同. class Ab(): a = 666 # 定义类对象Ab,自带属性a,值为666 # 使用Ab.__dict__可以查看类Ab的属性 us1 = Ab() us2 = Ab() # 定义两个实例对象us1.us2,这两个实例自身并不具备任何属性 # 只有在__init__中定义了self.arg=xxx的情况下,实例默认会具备arg属性 动态语言中,属性自带操作方法:获取(读).设置(写):还可以定义删除

【Python学习笔记】with语句与上下文管理器

with语句 上下文管理器 contextlib模块 参考引用 with语句 with语句时在Python2.6中出现的新语句.在Python2.6以前,要正确的处理涉及到异常的资源管理时,需要使用try/finally代码结构.如要实现文件在操作出现异常时也能正确关闭,则需要像如下实现: f = open("test.txt") try: for line in f.readlines(): print(line) finally: f.close() 不管文件操作有没有出现异常,t

python学习第十二天:闭包函数与装饰器

闭包函数: 什么是闭包函数: 闭指的是定义在一个函数内部 包指的是该函数包含对外部作用域(非全局作用域)名字的引用 def counter(): n=0 def incr(): nonlocal n x=n n+=1 return x return incr c=counter() print(c()) 闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域 装饰器 1.什么是装饰器 就目前来看:装饰器就是定义一

OpenCV之Python学习笔记

OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书<OpenCV Computer Vision with Python>,于是就看一遍,顺便把自己掌握的东西整合一下,写成学习笔记了.更需要的朋友参考. 阅读须知: 本文不是纯粹的译文,只是比较贴近原文的笔记:         请设法购买到出版社出版的书,支持正版. 从书名就能看出来本书是介绍在Pytho

廖Python学习笔记一

1. 廖Python学习笔记 大的分类 如函数 用二级标题,下面的用三级 如输入输出 1.1.1. 输入输出 1.1.1.1. 输出 用 print() 在括号里加上字符串,就可以向屏幕上输出指定的文字print()函数可以接受多个字符串,用逗号(,)隔开,依次输出遇到逗号输出一个空格.如图 1.1.1.2. 输入 提供了一个input(),可以让用户输入字符串,并存放到一个变量里. name = input() print(name) 1.1.2. 变量 是初中数学所学的代数基础知识的使用.

python学习笔记12-模块使用

python学习笔记12-模块使用 模块os,sys 什么是模块? 模块os,sys 模块是Python组织代码的一种基本方式 一个Python脚本可以单独运行,也可以导入到另外一个脚本运行,用import hello语句来导入,不用加入.py 什么是Python的 包? Python的模块可以按照目录组织为包 创建一个包的步骤: 创建一个名字为包名的目录 在改目录下创建一个__init__.py文件 根据需要,在该目录下存放脚本文件或已编译的扩展及子包 import pack.m1,pack.

python学习笔记2—python文件类型、变量、数值、字符串、元组、列表、字典

python学习笔记2--python文件类型.变量.数值.字符串.元组.列表.字典 一.Python文件类型 1.源代码 python源代码文件以.py为扩展名,由pyton程序解释,不需要编译 [[email protected] day01]# vim 1.py #!/usr/bin/python        print 'hello world!' [[email protected] day01]# python 1.py hello world! 2.字节代码 Python源码文件