当前位置 : 主页 > 编程语言 > python >

python--装饰器

来源:互联网 收集:自由互联 发布时间:2022-07-13
前戏 装饰器: 定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能 原则: 不能修改被装饰的函数的源代码 不能修改被装饰的函数的调用方式 实现装饰器知识储备 1.函

前戏

装饰器:
定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能

原则:

  • 不能修改被装饰的函数的源代码
  • 不能修改被装饰的函数的调用方式

实现装饰器知识储备

  1.函数即'变量'

  2.高阶函数

  • 把一个函数当做实参传递给另外一个参数(在不修改被装饰函数源代码的情况下为其添加功能)
  • 返回值中包含函数名(不修改函数的调用方式)

  3.嵌套函数(在一个函数的函数体内用def声明另一个函数)

无参数的装饰器

下面有一个函数,如果我们想统计一下函数执行的时间,使用装饰器怎么实现呢

import time


def test1():
time.sleep(2)
print('in the test1')

如果不使用装饰器我们可以在之前前加一个时间,执行后加一个时间就可以了,如下

import time


def test1():
start_time = time.time()
time.sleep(2)
print('in the test1')
print(time.time()-start_time)


test1()

但是这样的话,我们修改了源代码,如果这个函数有好多地方调用了,有些地方不希望要其他的功能,有些地方需要,难道我们需要重新写一个函数吗?在把调用到的地方都修改一下?如果你这样的话,明天就可以去财务领工资了。。。那来看看怎么使用装饰器来实现

1 import time
2
3
4 def timmer(func):
5 def warpper():
6 start_time = time.time()
7 func() # run test1
8 stop_time = time.time()
9 print('the func time is %s' % (stop_time - start_time))
10
11 return warpper
12
13
14 @timmer # test1=timmer(test1)语法糖,给哪个函数加装饰器,就在哪个函数前加上 @ 装饰名
15 def test1():
16 time.sleep(2)
17 print('in the test1')
18
19 test1() # 运行warpper()

代码解释:

函数从上往下执行,执行到14行的时候,14行的代码等价于test1=timmer(test1)。就回去执行timmer函数,所以timmer里的func就是test1。执行完返回了warpper,所以test1=warpper,然后执行19行,因为test1=warpper,所以19行相当于warpper(),执行了waepper函数,而func为test1,func()就是调用了test1()这个函数。

这样我们就实现了一个装饰器,在不修改源代码和调用方式的情况下给函数增加了新的功能。

带参数的装饰器

上面的test1函数没有参数,如果test1需要一个参数,还这样写的话就会报错

import time


def timmer(func):
def warpper():
start_time = time.time()
func() # run test1
stop_time = time.time()
print('the func time is %s' % (stop_time - start_time))

return warpper


@timmer
def test1(m1):
time.sleep(2)
print('in the test1')

test1('2')

结果:

TypeError: warpper() takes 0 positional arguments but 1 was given

报错信息告诉了我们warpper需要一个参数,那我们去修改一下

import time


def timmer(func):
def warpper(arg):
start_time = time.time()
func(arg) # run test1
stop_time = time.time()
print('the func time is %s' % (stop_time - start_time))

return warpper


@timmer
def test1(m1):
time.sleep(2)
print('in the test1')

test1('2')

我们给warpper传了一个参数arg,因为func(test1)是需要一个参数的,那如果test1需要多个参数怎么办呢,我们可以用可变参数*args,**kwargs来实现动态的传参

import time


def timmer(func):
def warpper(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs) # run test1
stop_time = time.time()
print('the func time is %s' % (stop_time - start_time))

return warpper


@timmer
def test1(m):
time.sleep(2)
print('in the test1')

test1('12')

这样不管test1有没有参数,有几个参数都能满足需求

有返回值的装饰器

还是上面的代码,假如test1里有返回值,如下

1 import time
2
3
4 def timmer(func):
5 def warpper(*args, **kwargs):
6 start_time = time.time()
7 func(*args, **kwargs) # run test1
8 stop_time = time.time()
9 print('the func time is %s' % (stop_time - start_time))
10
11 return warpper
12
13
14 @timmer
15 def test1():
16 time.sleep(2)
17 print('in the test1')
18 return 666
19
20 # test1()
21 print(test1())

结果:

in the test1
the func time is 2.0003857612609863
None

我们可以看到,结果返回了一个None,因为warpper函数的时候,在执行到func(*args, **kwargs)的时候,执行了test1函数,虽然是执行了,但是return返回的值没有接收,那我们可以定义一个变量接收一下,然后再return给调用者

1 import time
2
3
4 def timmer(func):
5 def warpper(*args, **kwargs):
6 start_time = time.time()
7 res = func(*args, **kwargs) # run test1
8 stop_time = time.time()
9 print('the func time is %s' % (stop_time - start_time))
10 return res
11
12 return warpper
13
14
15 @timmer
16 def test1():
17 time.sleep(2)
18 print('in the test1')
19 return 666
20
21 # test1('12')
22 print(test1())

这样的话,我们也实现了一个带返回值的装饰器,如果test1没有返回值,则返回的是None,在看个栗子,加深下理解

def auth(func):
def timer(*args, **kwargs):
print('加的新功能start。。。')
res = func(*args, **kwargs) # 将返回值得结果赋给res
print('加的新功能end。。。')
return res # 执行返回值的结果,没有不执行


return timer


@auth # test2=auth(test2)
def test2(*args, **kwargs):
print('in the test2...')
return '我是返回值'


print(test2('zou', 'IT', '24'))

结果:

加的新功能start。。。
in the test2...
加的新功能end。。。
我是返回值

实战

1 user, passwd = 'zou', '123'
2
3 def auth(func):
4 def timmer(*args, **kwargs):
5 username = input('输入用户名:')
6 password = input('输入密码:')
7 if username == user and password == passwd:
8 print('加的新功能')
9 res = func(*args, **kwargs) # 如果不将结果赋给res就没有返回值
10 return res
11 else:
12 exit('密码错误')
13 return timmer
14
15 def test1():
16 print('in the test1')
17
18
19 @auth
20 def test2(name, job):
21 print('name:%s' % name)
22 print('job:%s' % job)
23
24
25 @auth
26 def test3():
27 print('in the test3')
28 return 'end'
29
30
31 test1()
32 test2('zou', 'IT')
33 print(test3())

大家可以自己在脑海里想一下,是怎么运行的,为什么这么运行?最后运行的结果是什么?

结果:

python--装饰器_高阶函数

python--装饰器_新功能_02

in the test1
输入用户名:zou
输入密码:123
加的新功能
name:zou
job:IT
输入用户名:zou
输入密码:123
加的新功能
in the test3
end

点我偷看

 



上一篇:python-- socket介绍
下一篇:没有了
网友评论