python中的函数高级用法装饰器语法糖

函数可以被当做参数进行调用

装饰器的两种写法

第一种:方便理解

1
2
3
4
5
6
7
8
9
10
11
def func_1(func):
def func_2():
print('func_2')
func()
return func_2

def say():
print('fxxk python')

f = func_1(say)
f()

func_2
fxxk python

1、一开始通过执行 f = func_1(say),也就是说,把 say 这个方法传递给 func_1 函数;

2、那么这时候就会执行第二行,遇到了 func_2 函数然后 return 回来;

3、f 指向了这个 func_1 ;

4、接着执行 f() , 这时候就会执行第三行打印 fuc_2;

5、接着会向下执行 func(), 进入第 8 行打印 fxxk python。

你仔细看这个 func_1 函数,它的参数是接收一个函数,然后在内部使用它,最后返回的是另一个函数。

也就是说,一个函数,把另一个函数作为参数传进来,然后在内部去使用这个被传递进来的函数,
最后改变了这个函数的返回结果。我们就叫这个函数为装饰器。

所以,我们刚刚举得例子中, func_1 就是装饰器。

第二种 装饰器的最佳写法@

1
2
3
4
5
6
7
8
9
10
11
def func_1(func):
def func_2():
print('func_2')
func()
return func_2

@func_1
def say():
print('fxxk python')

say()

func_2
fxxk python

输出结果一样,这两段代码的意思相同,只是写法不同,而其中 @func_1 就是语法糖的写法
通过 @ + 函数名称,就可以实现直接将 say 函数传递给 func_1,如此就是装饰器的最佳写法

如何给装饰器传递参数

不明确指定参数

通过 args,*kwargs 接收任意参数

1
2
3
4
5
6
7
8
9
10
11
def func_1(func):
def func_2(*args, **kwargs):
print('func_2')
func(*args, **kwargs)
return func_2

@func_1
def say(something):
print(something)

say('fxxk python')

func_2
fxxk python

也可以明确指定参数

1
2
3
4
5
6
7
8
9
10
11
def func_1(func):
def func_2(ss):
print('func_2')
func(ss)
return func_2

@func_1
def say(something):
print(something)

say('fxxk python')

func_2
fxxk python

多个装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def func_1(func):
def func_inner(*args, **kwargs):
print('func_1')
func(*args, **kwargs)
return func_inner

def func_2(func):
def func_inner(*args, **kwargs):
print('func_2')
func(*args, **kwargs)
return func_inner

@func_1
@func_2
def say(something):
print(something)

say('fxxk python')

func_1
func_2
fxxk python

以上就是装饰器的用法,
它可以将逻辑代码和业务分离开来,
降低代码的耦合度,提高代码的使用率。
比如记录一些代码的 log ,检查用户的合法性,都可以使用装饰器来高效使用。

用户验证场景的装饰器使用

装饰器 user_check 实现用户合法性校验逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
def user_check(func):
def wrapper(username, password):
if (username != 'root'):
raise Exception('permission denied')
elif (password != '1234'):
raise Exception('password incorrect')
else:
return func(username, password)
return wrapper

@user_check
def login_user(username, password):
print('login success')
1
login_user('name', '1234')

用户名不是 root ,抛出异常

raise Exception(‘permission denied’)
Exception: permission denied

1
login_user('root', '1111')

密码不是 1234 ,抛出异常

raise Exception(‘password incorrect’)
Exception: password incorrect

用户合法

1
login_user('root', '1234')

login success!

只要别的地方需要验证用户合法性,就直接去引用这个装饰器 user_check 就可以了

以上就是装饰器的用法,
它可以将逻辑代码和业务分离开来,
降低代码的耦合度,提高代码的使用率。
比如记录一些代码的 log ,检查用户的合法性,都可以使用装饰器来高效使用。