python 装饰器

一、理论

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 装饰器函数 楔子 作为一个会写函数的python开发,我们从今天开始要去公司上班了。写了一个函数,就交给其他开发用...
    go以恒阅读 286评论 0 0
  • 说到装饰器,很明显就是用来装饰的,既然是要装饰,那肯定是在保留原有的基础上再添加一些东西作为装饰,这就是我对装饰器...
    张氏小毛驴阅读 254评论 0 0
  • 每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,...
    chen_000阅读 1,372评论 0 3
  • 「一個人對世界最大的貢獻,就是讓自己過的幸福」
    憨憨爹阅读 172评论 0 0
  • 说在前头: 今次谈的是“拍照”,准确说是“手机拍照”这个相对简单的技能。因尚不够格轻言摄影。 另,本文经验分享不包...
    连灿兴是个小木匠阅读 204评论 0 0