python装饰器
[TOC]
最近在学习flask,学到权限控制部分涉及到装饰器的知识,有点疑惑,所以网上四处搜集整理了一下。
路漫漫其修远兮,吾将上下而求索。
一、简介
在理解装饰器前需要先了解几个概念:
- python一切皆对象,所有对象都可作为参数传递。
- 闭包。
什么是闭包?
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。百度百科
可以归纳为以下几点:
- 闭包是嵌套函数;
- 内部函数读取外部函数的变量;
- 外部函数的返回值为内部函数;
类如:
1 | def outer(v): |
那么什么是装饰器?它又有什么作用呢?
装饰器: 装饰器顾名思义就是对一个函数进行装饰,为其添加一些附属功能的同时又不改变被装饰函数的一个函数。
作用:主要作用有框架的路由传参(如flask的app.route('/)
)、权限验证、插入日志、事务处理、缓存等。
二、示例
计算一个函数运行的时间
1 | import random, time |
三、python内置装饰器
python常用的内置装饰器有:
@classmethod:经过该装饰器装饰过的方法为类方法,第一个参数必须是clc(默认),只能通过类名.方法或对象名._class_.方法调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class A():
'''基类'''
def print_class_name(clc):
print(clc.__name__)
def print_hi(self):
print("hi")
a = A()
a.print_hi()
a.__class__.print_class_name()
A.print_class_name()
'''
输出:
hi
A
A
'''- staticmethod:该装饰器装饰的方法为静态方法,该方法不需要访问实例属性和类属性,使用类名.方法、对象名._class_.方法或对象名._class_.方法调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class A():
'''基类'''
def print_hi():
print("hi")
a = A()
a.print_hi()
a.__class__.print_hi()
A.print_hi()
'''
输出:
hi
hi
hi
'''- @property:该装饰器装饰过的方法可看作一个属性,可直接通过类名.方法名调用。
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
27class Person():
'''基类'''
__name = None
def __init__(self, name):
self.__name = name
def name(self):
return self.__name
def name(self, name):
self.__name = name
p = Person("张三")
print(p.name)
p.name = "李四"
print(p.name)
'''
输出:
张三
李四
'''
四、缺点
- 装饰器会对原函数的元信息进行修改,如函数的docstring,_name_,参数列表;
1 | def run_time(func): |
这个问题可以用python内置的一个装饰器wraps来解决,它会将原函数的所有原信息拷贝到装饰器函数中,使得装饰器函数的所有信息和原函数一致。
1 | from functools import wraps |
- 被@staticmethod 和 @classmethod装饰过的函数不能再被装饰。
- 不要在装饰器外添加逻辑功能。
参考
https://www.cnblogs.com/whyaza/p/9505205.html
https://blog.csdn.net/love20165104027/article/details/82934312