闭包

闭包就是能够读取其他函数内部变量的函数。

装饰器应用场景

装饰器的强大在于它能够在不修改原有业务逻辑的情况下对代码进行扩展,权限校验、用户认证、日志记录、性能测试、事务处理、缓存等都是装饰器的绝佳应用场景,它能够最大程度地对代码进行复用。

常用装饰器

1、函数装饰函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def wrapFun(func):
def inner(a, b):
print('function name:', func.__name__)
r = func(a, b)
return r
return inner

@wrapFun # myadd = wrapFun(myadd)
def myadd(a, b):
return a + b

print(myadd(2, 3))

结果:
function name: myadd
5

2、函数装饰函数(带参数)

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
def logging(level):
def wrapper(func):
def inner_wrapper(*args, **kwargs):
print("[{level}]: enter function {func}()".format(
level=level,
func=func.__name__))
return func(*args, **kwargs)

return inner_wrapper

return wrapper


@logging(level='INFO')
def say(something):
print("say {}!".format(something))


# 如果没有使用@语法,等同于
# say = logging(level='INFO')(say)

@logging(level='DEBUG')
def do(something):
print("do {}...".format(something))


if __name__ == '__main__':
say('hello')
do("my work")

结果:
[INFO]: enter function say()
say hello!
[DEBUG]: enter function do()
do my work...

3、类装饰函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class logging(object):
def __init__(self, func):
self.func = func

def __call__(self, *args, **kwargs):
print("[DEBUG]: enter function {func}()".format(
func=self.func.__name__))
return self.func(*args, **kwargs)


@logging
def say(something):
print("say {}!".format(something))


if __name__ == '__main__':
say("hello")

结果:
[DEBUG]: enter function say()
say hello!

4、类装饰函数(带参数)

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
class logging(object):
def __init__(self, level='INFO'):
self.level = level

def __call__(self, func): # 接受函数
def wrapper(*args, **kwargs):
print("[{level}]: enter function {func}()".format(
level=self.level,
func=func.__name__))
func(*args, **kwargs)

return wrapper # 返回函数


@logging(level='INFO')
def say(something):
print("say {}!".format(something))


if __name__ == '__main__':
say("hello")

结果:
[INFO]: enter function say()
say hello!

5、类实例方法装饰函数

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
class NotFlask:
def __init__(self):
self.routes = {}

def route(self, route_str):
def decorator(f):
self.routes[route_str] = f
return f

return decorator

def serve(self, path):
view_function = self.routes.get(path)
if view_function:
return view_function()
else:
raise ValueError('Route "{}"" has not been registered'.format(path))


app = NotFlask()


@app.route("/")
def hello():
return "Hello World!"


print(app.serve("/"))

结果:
Hello World!

6、类实例方法装饰函数(复杂参数)

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
45
46
47
48
49
50
import re


class NotFlask:
def __init__(self):
self.routes = []

@staticmethod
def build_route_pattern(route):
route_regex = re.sub(r'(<\w+>)', r'(?P\1.+)', route)
return re.compile("^{}$".format(route_regex))

def route(self, route_str):
def decorator(f):
route_pattern = self.build_route_pattern(route_str)
self.routes.append((route_pattern, f))

return f

return decorator

def get_route_match(self, path):
for route_pattern, view_function in self.routes:
m = route_pattern.match(path)
if m:
return m.groupdict(), view_function

return None

def serve(self, path):
route_match = self.get_route_match(path)
if route_match:
kwargs, view_function = route_match
return view_function(**kwargs)
else:
raise ValueError('Route "{}"" has not been registered'.format(path))


app = NotFlask()


@app.route("/hello/<username>")
def hello_user(username):
return "Hello {}!".format(username)


print(app.serve("/hello/ains"))

结果:
Hello ains!

参考链接

http://python.jobbole.com/80956/
http://python.jobbole.com/80993/