您的位置:首页 > 编程语言 > Python开发

Python 学习 - 装饰器

2017-03-31 00:00 302 查看
这一节了解了一些装饰器的简单使用。

首先来看一个预备知识,把一个函数当做参数,传入另外一个函数

比如说我传递outer(f1),我传入的是f1的内存地址,a=func()其实执行了f1()这个函数,并把返回值赋给了a,因此当我打印print(a),他会输出hee

1
2
3
4
5
6
7
8
9
10
11
12
>>>
def
outer(func):

print
(func)

a
=
func()

print
(a)

def
f1():

print
(
"aaa"
)

return
"hee"

outer(f1)

-
-
-
-
-
-
-
-
-
-
-
-

<function f1 at
0x0000023D3FF3D510
>

aaa

hee

装饰器(decorator)就是利用可以把函数当做传递这一点,他可以统一给一些函数添加一些“修饰”功能,但是又不会去破坏原有的代码。装饰器本身也是一个函数,其他函数调用他的时候,在其他函数前面 @ +装饰器名的格式就行了

这个格式执行了2个功能:

1. 自动执行装饰器函数并且将其下面的函数名f1当作参数传递

2. 将装饰器函数的返回值,重复赋值给 f1

简单的说就是这样

f1=decortor(f1)

把上面的例子稍微修改成装饰器,如下所示,结果是一样的

1
2
3
4
5
6
7
8
9
10
11
12
def
outer(func):

def
innner(
*
args,
*
*
kwargs):

print
(func)

a
=
func(
*
args,
*
*
kwargs)

print
(a)

return
a

return
innner

@outer

def
f1():

print
(
"aaa"
)

return
"hee"

f1()

再看另外一个复杂一些的例子:

我定义了3个函数f1,f2,f3,他们有不同的参数,我需要每个函数在现在的结果前面添加一个'before',结果后面添加一个‘after’

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
def
outer(func):

def
inner(
*
args,
*
*
kwargs):

print
(
'before'
)

r
=
func(
*
args,
*
*
kwargs)

print
(
'after'
)

return
r

return
inner


@outer

def
f1(arg):

print
(arg)

return
"F1"


@outer

def
f2(a1,a2):

print
(
"F2"
)


@outer

def
f3():

print
(
"F3"
)



f1(
"hhh"
)

f2(
"bbb"
,
444
)

f3()

结果如下:

1
2
3
4
5
6
7
8
9
before

hhh

after

before

F2

after

before

F3

after

注意要点:

当使用装饰器outer的时候,他传递参数 outer(f1),这里传递的是f1的地址;r=func()其实执行的就是f1(),然后把返回值赋给了r,这里的目的是为了保证inner返回的结果和f1返回的结果一样;最后再把装饰过的inner函数地址赋给f1,实现装饰的效果;

记得前面的万能参数 f(*args,**kwargs),可以接受任意的参数

例2:装饰器一个广泛使用的场景是登录验证;很多功能必须判断登录之后才能使用。

下面的例子装饰器通过一个全局变量LOGIN_USER来判断是否已经登录。

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
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/env python

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


LOGIN_USER
=
{
"is_login"
:
False
}

def
outer(func):

def
inner(
*
args,
*
*
kwargs):

if
LOGIN_USER[
'is_login'
]:

r
=
func()

return
r

else
:

print
(
"请登录"
)

return
inner

def
outer1(func):

def
inner(
*
args,
*
*
kwargs):

if
LOGIN_USER[
'is_login'
]
and
LOGIN_USER[
'user_type'
]
=
=
2
:

r
=
func()

return
r

else
:

print
(
"请登录,或者权限不够"
)

return
inner

@outer1

def
order():

print
(
"欢迎%s登录"
%
LOGIN_USER[
'current_user'
])

@outer

def
changepwd():

print
(
"欢迎%s登录"
%
LOGIN_USER[
'current_user'
])

@outer

def
manager():

print
(
"欢迎%s登录"
%
LOGIN_USER[
'current_user'
])

def
login(user,pwd):

if
user
=
=
"alex"
and
pwd
=
=
"123"
:

LOGIN_USER[
'is_login'
]
=
True

LOGIN_USER[
'current_user'
]
=
user

manager()

def
main():

while
True
:

inp
=
input
(
"1,后台管理;2,登录"
)

if
inp
=
=
'1'
:

manager()

elif
inp
=
=
'2'
:

username
=
input
(
"请输入用户名"
)

pwd
=
input
(
"请输入密码"
)

login(username,pwd)

main()

例3.

如果有多个装饰器,我可以嵌套的使用,因为一层的装饰器之后其实也是一个函数,那他自然可以再继续被装饰。

比如说,注意他的调用顺序是从下往上的

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
Python
3.5
.
2
(v3.
5.2
:
4def2a2901a5
,Jun
25
2016
,
22
:
18
:
55
) [MSC v.
1900
64
bit (AMD64)]on win32

>>>
def
outer(func):

def
innner(
*
args,
*
*
kwargs):

print
(func)

a
=
func(
*
args,
*
*
kwargs)

print
(
"装饰1"
)

return
a

return
innner

def
outer2(func):

def
inner(
*
args,
*
*
kwargs):

print
(func)

a
=
func(
*
args,
*
*
kwargs)

print
(
"装饰2"
)

return
a

return
inner

@outer2

@outer

def
f1():

print
(
"原函数"
)

return
"hee"

f1()

<function outer.<
locals
>.innnerat 
0x000001FF89A6D620
>

<function f1 at
0x000001FF89A6D598
>

原函数

装饰
1

装饰
2





登录乐搏学院官网http://www.learnbo.com/

或关注我们的官方微博微信,还有更多惊喜哦~



本文出自 “麻婆豆腐” 博客,请务必保留此出处http://beanxyz.blog.51cto.com/5570417/1844747
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: