Contents
  1. 1. Python的修饰器
    1. 1.1. 原理解释
  2. 2. 多线程

Python的修饰器

先看一个很常见的例子

req.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def before_request(func):
def inner(*args, **kwargs):
print('before_request...', args, kwargs)
return func(*args, **kwargs)
return inner
def after_request(func):
def inner(*args, **kwargs):
result = func(*args, **kwargs)
print('after_request...')
return result
return inner
@after_request
@before_request
def index(a,b,c):
print('render index.....')
if __name__ == '__main__':
index([],2,c='fk')

输出

1
2
3
before_request... ([], 2) {'c': 'fk'}
render index.....
after_request...

原理解释

你写了一个很棒的通用方法,但是有点长。但是老板这时候来了需求,要求它在不同的情况下进行一些不同的操作(例如不同情境下的验证操作)。为了遵循封闭开发原则,尽量不去改已经完成的代码,或许修饰器是一个不错而优雅的选择。

先举个简单例子

1
2
3
4
5
6
7
def awesome_method():
# do a lot!
print('main func')
def before_do_that():
# ready for that
print('before func')

你想在函数awesome_method前先执行before_do_that,并且要在同一个context下,如果直接修改通用代码,不仅不简洁,而且不优雅。这个时候你利用修饰符稍加修改:

1
2
3
4
5
6
7
8
9
10
11
@before_do_that
def awesome_method():
# do a lot!
print('main func')
def before_do_that(func):
def inner():
# ready for that
print('before func')
return func()
return inner

这里解释一下,在一个函数添加一个修饰符,相当于把awesome_method作为before_do_that的参数,转换成了一个新的同名函数,这里的before_do_that相当于一个工厂,进去的函数都必须通过加工。

那么多个修饰符的情况下,代码执行顺序如何?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def w1(func):
def inner():
print('w1 ready go')
return func()
return inner
def w2(func):
def inner():
print('w2 ready go')
return func()
return inner
@w2
@w1
def f1():
print('f1')

若执行f1(),此时相当于

1
w2(w1(f1))()

输出

1
2
3
w2 ready go
w1 ready go
f1

带参数写法如下,这次用after举例

1
2
3
4
5
6
7
8
9
10
def after_request(func):
def inner(*args, **kwargs):
result = func(*args, **kwargs)
print('after_request...', args, kwargs)
return result
return inner
@after_request
def index(a,b,c):
print('render index.....')

此时执行 index([],2,c='fk'),输出:

1
2
render index.....
after_request... ([], 2) {'c': 'fk'}

**表示对键值对的引用,关于**的用法,我们可以甚至可以写一个漂亮的字典构造函数:

1
2
3
>>> a=lambda **x:x
>>> a(a=2,c=2)
{'c': 2, 'a': 2}

如果多个修饰符写的不好看,还有修饰符带参数的闭包写法

dec.py

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
def Before(request, kargs):
print('some thing before..')
def After(request, kargs):
print('some thing after..')
def Filter(before_func, after_func):
def outer(main_func):
def wrapper(request, kargs):
before_result = before_func(request, kargs)
if (before_result != None):
return before_result
main_result = main_func(request, kargs)
if (main_result != None):
return main_result
after_result = after_func(request, kargs)
if (after_result != None):
return after_result
return wrapper
return outer
@Filter(Before, After)
def Index(request, kargs):
print('index')
if __name__ == '__main__':
Index([],2,c='fk')

这个闭包利用了Filterouter的三个参数函数,重新改写执行顺序,直到其中有一个函数抛出返回值为止。

至此关于修饰符的内容基本交代完毕

多线程

// Todo:

Contents
  1. 1. Python的修饰器
    1. 1.1. 原理解释
  2. 2. 多线程