装饰器(傻逼看的懂版)

装饰器的作用——

在不改变函数原代码、调用方式的条件下,对函数增添额外的功能。

 

 

装饰器的组成:

高阶函数

函数嵌套

 

 

高阶函数:

 

什么是函数?

函数是对代码段的封装,函数是可执行的,执行函数就是

运行函数中封装的代码段。

 

通过内置方法,可以看到函数是可调用的!

>>> def foo():

...     print('hello,world')

...

>>> callable(foo)

True

 

函数到底是什么?

‘function’???

 

>>> print(foo)

<function foo at 0x0051C660>

 

很明确,其实函数就是一个内存地址,函数名就是类似于内存地址的指针,对调用函数就是运行对应的内存地址!

 

什么是变量:

>>> name = 'alben'

>>> mingzi = 'alben

 

 

 

如图所示,变量命名就是把一个内存地址赋值到变量名(内存调用)

 

Python的内存回收:

当一个内存地址的所有调用都被del的时候,该内存被释放,否则将随着程序的运行永远占用。

 

那么变量与内存有没有区别呢?

答案是没有——

>>> def foo():

...     print('Hello,World')

...

>>> abc = foo

>>> print(abc)

<function foo at 0x0047C660>

>>> print(foo)

<function foo at 0x0047C660>

>>> 

 

高阶函数:

把一个A函数的函数名作为实参传递给B函数,B函数就是高阶函数

 

举例:

import time

 

def foo():

    time.sleep(3)

    l1 = [i * 2 for i in range(1000)]

    print(len(l1))

 

 

def calc_time(func):

    start_time = time.time()

    func()

    end_time = time.time()

    print('The Func %s run time is %d' %(func,(end_time-start_time)))

 

calc_time(foo)

 

通过calc_time函数,可以计算函数foo的运行耗时。

 

but:

虽然函数我们实现了不改变函数foo的原代码情况下,增加了一个计算运行时间的功能,这是不可取的!

 

函数嵌套:

在一个函数的内部定义另一个函数,这个行为就是函数嵌套

def foo():

    def inner():

        print("This is inner func")

这个就是函数嵌套!

 

通过函数嵌套+高阶函数实现对现有函数功能的增加!

伪代码:

import time

 

def foo():

    time.sleep(3)

    l1 = [i * 2 for i in range(1000)]

    print(len(l1))

 

 

def calc_time(func):

    def inner():

        start_time = time.time()

        func()

        end_time = time.time()

        print('the Func %s run time is %d ' %(func,(end_time-start_time)))

    return inner

1、定义了一个函数calc_time,该函数是高阶函数,要求传入另一个函数的函数名

2、函数calc_time内进行了函数套嵌,内嵌了另一个函数inner,

3、函数calc_time的return值就是内嵌函数inner

分析函数inner!

1、记录和执行时间(start_time)

2、执行了那个被当做实参传递进calc_time的函数

3、记录了执行完成时间(end_time)

4、计算了被传入函数的执行时间!

 

内嵌函数inner是不能直接在解释器中运行的!会出现如下报错!

Traceback (most recent call last):

  File "D:/实现自动化运维/高阶函数.py", line 21, in <module>

    inner()

NameError: name 'inner' is not defined

 

但是,函数calc_time的return就是内嵌函数的函数名!,所以我们只需要把calc_time的返回值赋值到一个变量,对这个变量执行以下就是执行内嵌函数inner了。

def foo():

    time.sleep(3)

    l1 = [i * 2 for i in range(1000)]

    print(len(l1))

 

 

def calc_time(func):

    def inner():

        start_time = time.time()

        func()

        end_time = time.time()

        print('the Func %s run time is %d ' %(func,(end_time-start_time)))

    return inner

 

 

abc = calc_time(foo)

 

abc()

 

结果:

1000

the Func <function foo at 0x0049B660> run time is 3

 

我们已经实现了不改变函数foo源代码的条件下增加了新的功能(计算时间),

but!调用方式改变了!!

有一个折中的方案:

foo = calc_time(foo)

 

foo()

这样!简直prefect!

 

装饰器的雏形就出来了,python解释器给我们提供了一个语法糖!“@”来实现这个功能!

代码:

#!/usr/bin/env python3

#-*- coding:utf-8 -*-

 

  1. import time
  2. def calc_time(func):
  3.     def inner():
  4.         start_time = time.time()
  5.         func()
  6.         end_time = time.time()
  7.         print('the Func %s run time is %d ' %(func,(end_time-start_time)))
  8.     return inner
  9. @calc_time
  10. def foo():
  11.     time.sleep(3)
  12.     l1 = [i * 2 for i in range(1000)]
  13.     print(len(l1))
  14. foo()

 

在pycharm的Debug中,可以清晰的看到代码的执行顺序如下:

2-9-3-8-14-4-5-11-12-13-6-7

 

这就是最简单的装饰器!

 

下面,思考一个问题!就是如果被装饰的函数带有参数,那怎么办!

 

有一个推算斐波那契数列的函数:

def foo(a,b,x):

    if type(a) and type(b) == int:

        l1 = [a,b]

        while True:

            c = l1[-1] + l1[-2]

            l1.append(c)

            if c >x :break

    else:

        print("please give two int")

    print (l1)

 

现在想要通过上面的装饰器calc_time来对这个函数进行装饰,试一下:

@calc_time

def foo(a,b,x):

    if type(a) and type(b) == int:

        l1 = [a,b]

        time.sleep(1)

        while True:

            c = l1[-1] + l1[-2]

            l1.append(c)

            if c > x : break

    else:

        print("please give two int")

    print(l1)

 

foo(1,2,1000)

 

运行结果:

"C:\Users\IE-LAB Dade\AppData\Local\Programs\Python\Python36-32\python.exe" D:/实现自动化运维/高阶函数.py

Traceback (most recent call last):

  File "D:/实现自动化运维/高阶函数.py", line 26, in <module>

    foo(1,2,1000)

TypeError: inner() takes 0 positional arguments but 3 were given

 

Process finished with exit code 1

 

不用我提示了把,只需要把装饰器内部套嵌的函数加上可变参数就可以了!

def calc_time(func):

    def inner(*args,**kwargs):

        start_time = time.time()

        func(*args,**kwargs)

        end_time = time.time()

        print('the Func %s run time is %d ' % (func, (end_time - start_time)))

    return inner

 

好了,我相信白痴看了这个都能理解装饰器了吧!

 

转载于:https://www.cnblogs.com/alben-cisco/p/7197891.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值