python 装饰器

2018-10-16  本文已影响0人  SlashMan

一、理论

1、装饰器定义

本质上是函数(装饰其他函数),就是为其他函数添加附加功能。

2、原则

1、不能修改被装饰的函数的源代码

2、不能修改被装饰的函数的调用方式

3、实现装饰器知识储备:

1.函数即“变量”

2.高阶函数(a.把一个函数名当做实参传给另外一个函数(不修改被装饰函数源代码的情况下为其添加功能);b.返回值中包含函数名(不修改函数的调用方法))

3.嵌套函数

而高阶函数 + 嵌套函数 = 装饰器

二、实现

先说一下高阶函数,高阶函数的定义上面已经说了(a、把一个函数名当做实参传给另外一个函数;b.返回值中包含函数名)。只要实现了a条件就是高阶函数,b为可选条件。

现在有一个最原始的函数func

def func():

    time.sleep(3)

    print("in the func")

现在要写一个高阶函数,要把func以一个参数的形式传入这个高阶函数中,并给func函数添加一个计算func函数运行时间的功能

def test1(func):

      start_time = time.time()

      func()

      stop_time = time.time()

      print("the func run time is %s" % (stop_time - start_time))

此时如果要实现功能的话只需要调用test1就行了,这样的话不符合装饰器的原则。

那如何在调用func的同时也实现想要进行装饰的功能(计算func的运行时间)那。

我们用嵌套函数试试

def foo():

      print("in the foo")

      def func():

      time.sleep(3)

      print("in the func")

      start_time = time.time()

      func()

      stop_time = time.time()

      print("the run time is %s" % (stop_time - start_time))

此时也是只要调用foo函数就行了。和用高阶函数一样。那我如何在调用func 的同时也能实现附加功能那。此时不防用高阶函数 + 嵌套函数来试试。我先用一个高阶函数来接受func作为参数,然后在高阶函数中嵌套一个函数来添加附加功能。并将嵌套的函数作为返回值传出来。

def test5(func):

      def test4():

            start_time = time.time()

            func()

            stop_time = time.time()

            print("the run time is %s" % (stop_time - start_time))

      return test4

此时如果应该怎样去调用这些函数那,我们需要定义一个变量来接受test4(添加附件功能的函数),然后定义这个函数就可以了。

func = test5(func)

func()

此时的func实际上就是test5中嵌套的test4。运行程序,此时的打印结果为

in the test3

the run time is 3.0007569789886475

基本上实现了装饰器的功能,但是也改变了原函数的调用方法。在python中有一个装饰器的修饰方法。就是在原函数的上一行加上“@装饰器函数”。这样就可以直接调用原函数,而且实现附加功能了。例如上面我们是用test5来作为func的装饰器函数的,此时如果在func的定义函数的上一行加上“@test5”,此时只需要调用func函数也能实现附加功能

@test5

def func():

time.sleep(3)

    print("in the func")

现在调用直接调用func函数也能实现附加功能了。而这里的“@test5”的功能就相当于“func = test5(func)”。到此装饰器就实现了。但是如果func函数也是有参数传入的那应该怎么办那。上面说过了其实被装饰器装饰过的函数,在调用时,实际上是调用的装饰器函数中嵌套的函数,那么我们在嵌套函数的定义中也写上参数不就解决了嘛。是的。但是参数的个数是不确定的,如何在不确定参数的情况下,接受全部参数,如下所示

def test5(func):

      def test4(*args, **kwargs):

            start_time = time.time()

            func(*args, **kwargs)

            stop_time = time.time()

            print("the run time is %s" % (stop_time - start_time))

      return test4

这样装饰器就完全实现了。

现在有两个函数,表示两种不同的登录方式,一个是本地登录,另外一个是需要远程连接服务器认证的。那么如何同时给这两个函数,区别去添加功能,并且将第一个函数的返回值也传出去。首先需要给装饰器传入一个参数来区别两种登录方式。

#第一个登录函数(有返回值)

@auth(auth_type="local")

def login(*args, **kwargs):

      print("welcome to home page")

      return "from home"

第二个登录函数

@auth(auth_type="ldap")

def loginTwo(*args, **kwargs):

      print("welcome to loginTwo page")

此时装饰器1、多嵌套一层来接受auth_type参数,2、如下如所示红框内为返回原函数的返回值。

图1

代码下载:https://github.com/zhangyunf/python-.git

上一篇 下一篇

猜你喜欢

热点阅读