简介:

装饰器(Decorators)是 Python 的一个重要部分。简单地说:他们是修改其他函数的功能的函数。

比如说我们写flask,路由就是用装饰器定义的。如果写权限控制,那么权限控制一般也是由装饰器来实现的。日志记录,一般也可以通过装饰器来实现。

简单说,就是为了给某些函数增加一种或几种功能的做法。

下面举例实现。

一:基本函数

1.源码

from time import sleep

def watch_movie():
print('看电影')
sleep(3)
print('The End') if __name__ == '__main__':
watch_movie()

2.执行结果

代码很简单,先打印看电影,间隔3秒,打印The End。

二:装饰器原理

1.目标:计算函数运行时间

2.源码

from time import sleep, time

def ceal_time():
before = time()
watch_movie()
after = time()
print('函数运行%s秒' % (after - before)) def watch_movie():
print('看电影')
sleep(3)
print('The End') if __name__ == '__main__':
ceal_time()

3.执行结果

代码很简单,先打印看电影,间隔3秒,打印The End,然后打印函数运行计时。

4.分析

我们把一个函数放进另一个函数去运行,这就是装饰器的基本工作原理。

三:改造计时函数为通用函数

1.目标:把计算函数运行时间这个功能,适配给不同的函数。

2.源码

from time import sleep, time

def ceal_time(fun):
before = time()
fun()
after = time()
print('函数运行%s秒' % (after - before)) def watch_movie():
print('看电影')
sleep(3)
print('The End') def play_game():
print('玩游戏')
sleep(3)
print('Game Over') if __name__ == '__main__':
ceal_time(watch_movie)
ceal_time(play_game)

3.执行结果

看电影和玩游戏两个函数都执行了。

4.分析

我们可以把函数作为对象,传入另一个函数当中。

四:变为装饰器

1.目标:

我们改变了函数的调用方式,能不能不改变函数在调用位置的代码呢?

2.源码:

from time import sleep, time

def ceal_time(fun):
def wrapper():
before = time()
fun()
after = time()
print('函数运行%s秒' % (after - before)) return wrapper @ceal_time
def watch_movie():
print('看电影')
sleep(3)
print('The End') # @ceal_time
def play_game():
print('玩游戏')
sleep(3)
print('Game Over') if __name__ == '__main__':
watch_movie()
play_game()

3.执行结果

看电影前面加了装饰器,实现了函数运行计时,玩游戏没有加装饰器,所以没有函数运行计时。

而且函数在main中的调用方式和没加装饰器是一样的。

五:函数有参数

1.目标:被装饰的函数,有参数的处理

2.源码:

from time import sleep, time

def ceal_time(fun):
def wrapper(*args, **kwargs): # 修改
before = time()
fun(*args, **kwargs) # 修改
after = time()
print('函数运行%s秒' % (after - before)) return wrapper @ceal_time
def watch_movie(name, movie):
print('%s在看%s电影' % (name, movie))
sleep(3)
print('The End') # @ceal_time
def play_game(name, game):
print('%s在玩%s游戏' % (name, game))
sleep(3)
print('Game Over') if __name__ == '__main__':
watch_movie(name='张三', movie='猫和老鼠')
play_game(name='李四', game='魔兽争霸')

3.执行结果

你可以试试看,没有了*args,**kwargs,一定是会报错的。

六:有返回值的函数加装饰器

1.目标:现在做的都没返回值,如何处理被装饰的函数的返回值。

2.源码:

from time import sleep, time

def ceal_time(fun):
def wrapper(*args, **kwargs):
before = time()
result = fun(*args, **kwargs) # 修改
after = time()
print('函数运行%s秒' % (after - before))
return result # 返回 return wrapper @ceal_time
def watch_movie(name, movie):
print('%s在看%s电影' % (name, movie))
sleep(3)
print('The End')
return '电影看完了' # @ceal_time
def play_game(name, game):
print('%s在玩%s游戏' % (name, game))
sleep(3)
print('Game Over')
return '游戏玩完了' if __name__ == '__main__':
print(watch_movie(name='张三', movie='猫和老鼠'))
print(play_game(name='李四', game='魔兽争霸'))

3.执行结果

现在已经可以处理任何函数的装饰器操作了。

七:权限登录

1.目标:

flask中未登录用户进入登录页面

flask中登录用户进入详情页面

2.源码一(无装饰器):

无装饰器,简单判断session存在即可进入。

import os

from flask import Flask, request, g, redirect, url_for, session

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24) def ceal_time(fun):
def wrapper(*args, **kwargs):
result = fun(*args, **kwargs) # 修改
return result # 返回 return wrapper @app.route('/')
def index():
return '欢迎页面' @app.route('/login/', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
html = '''
<form action="" method="post">
<table>
<tbody>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" placeholder="请输入用户名"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password" placeholder="请输入密码"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="登录"></td>
</tr>
</tbody>
</table>
</form>'''
return html
if request.method == 'POST':
session['sign'] = True
return redirect(url_for('info'))
return '登录' @app.route('/info/')
def info():
if session.get('sign'):
return '详情页'
else:
return redirect(url_for('login')) if __name__ == '__main__':
app.run()

3.源码二(有装饰器):

import os

from flask import Flask, request, g, redirect, url_for, session

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24) def check_auth(fun):
def wrapper(*args, **kwargs):
if session.get('sign'):
return fun(*args, **kwargs) # 修改
else:
return redirect(url_for('login')) return wrapper @app.route('/')
def index():
return '欢迎页面' @app.route('/info/')
@check_auth
def info():
return '详情页' @app.route('/login/', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
html = '''
<form action="" method="post">
<table>
<tbody>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" placeholder="请输入用户名"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password" placeholder="请输入密码"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="登录"></td>
</tr>
</tbody>
</table>
</form>'''
return html
if request.method == 'POST':
session['sign'] = True
print(session.get('sign'))
return redirect('/info/')
# return redirect(url_for('info')) #这里写url_for会出错,但是session也创建成功,直接硬跳转吧。 if __name__ == '__main__':
app.run()

四:验证

1,访问http://127.0.0.1:5000/       欢迎页面

2,访问http://127.0.0.1:5000/login    登录页面

3,访问http://127.0.0.1:5000/info     自动进入登录页面,

4,登录页面点击提交,进入login的POST模式,设置session,然后自动进入详情页面。

5,装饰器的登录验证就这样。

python装饰器 语法糖的更多相关文章

  1. python 装饰器(语法糖)

    def  login(func):    def testlogin():        for  i in range(3):            _username="abc" ...

  2. python装饰器语法

    @就是decorator,早Python的高效开发中会用到,当然和java的annotation有一定的相似,但又不完全相同,看这篇文章:https://blog.csdn.net/zkp_987/a ...

  3. python装饰器总结

    一.装饰器是什么 python的装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.简单的说装饰器就是一个用来返回函数的函数 ...

  4. Python 装饰器入门(上)

    翻译前想说的话: 这是一篇介绍python装饰器的文章,对比之前看到的类似介绍装饰器的文章,个人认为无人可出其右,文章由浅到深,由函数介绍到装饰器的高级应用,每个介绍必有例子说明.文章太长,看完原文后 ...

  5. Python 装饰器的诞生过程

    ​ Python中的装饰器是通过利用了函数特性的闭包实现的,所以在讲装饰器之前,我们需要先了解函数特性,以及闭包是怎么利用了函数特性的 ① 函数特性 Python中的函数特性总的来说有以下四点: 1. ...

  6. Python装饰器AOP 不定长参数 鸭子类型 重载(三)

    1 可变长参数与关键字参数 *args代表任意长度可变参数 **kwargs代表关键字参数 用*args和**kwargs只是为了方便并没有强制使用它们. 缺省参数即是调用该函数时,缺省参数的值若未被 ...

  7. Python装饰器完全解读

    1 引言 装饰器(Decorators)可能是Python中最难掌握的概念之一了,也是最具Pythonic特色的技巧,深入理解并应用装饰器,你会更加感慨——人生苦短,我用Python. 2 初步理解装 ...

  8. Python 装饰器执行顺序

    Python 装饰器执行顺序 之前同事问到两个装饰器在代码中使用顺序不同会不会有什么问题,装饰器是对被装饰的函数做了一层包装,然后执行的时候执行了被包装后的函数,例如: def decorator_a ...

  9. 一篇文章搞懂Python装饰器所有用法

    01. 装饰器语法糖 如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上 ...

随机推荐

  1. JavaScript数组常用操作方法

    ES5操作数组的方法 1.concat() concat() 方法用于连接两个或多个数组.该方法不会改变现有的数组,仅会返回被连接数组的一个副本. var arr1 = [1,2,3]; var ar ...

  2. Python库的使用之-Sys模块

    Python标准库之sys模块使用详解,讲解了使用sys模块获得脚本的参数.处理模块. 使用sys模块操作 模块搜索路径.使用sys模块查找内建模块.使用sys模块查找已导入的模块,重定向输出以及重定 ...

  3. async 珠峰培训node正式课笔记 【async】任务流程控制,异步流程控制

    var async = require('async'); // series 串形任务 console.time('cost') async.series({ two:function(callba ...

  4. 热修复技术沉思:jspatch

    硬修复: 直接修改工程源码,重新发版: 冷修复: 打补丁包,使用动态库和hook技术,在程序启动时完成问题代码修复:案例:iOS逆向工程: 特征:不修改原始代码.补丁发布.目前不支持动态发布: 热修复 ...

  5. 用Python 打开程序的两中方法

    1.ShellExecute函数 import win32api win32api.ShellExecute(0, 'open', 'notepad.exe', '', '', 0) # 后台执行 w ...

  6. 基于docker-compose部署 简单nsq 集群

    主要目的是搭建一个测试环境,同时使用了nodejs 客户端sdk nsq 简单了解 nsqd:一个负责接收.排队.转发消息到客户端的守护进程 nsqlookupd:管理拓扑信息并提供最终一致性的发现服 ...

  7. 2.Servlet入门

    一.Servlet简介 Servlet为sun公司开发动态web的一门技术 Sun公司在这些API中提供了一个接口叫做:Servlet,如果想开发Servlet程序,需要完成两个小步骤: 编写一个类, ...

  8. 鸿蒙OS

    8月9日,华为消费者业务在其全球开发者大会上正式发布其全新的基于微内核的面向全场景的分布式操作系统——鸿蒙OS(HarmonyOS)! 鸿蒙的定义是基于微内核的全场景分布式操作系统.其中,微内核是技术 ...

  9. 提前体验让人"回归Windows怀抱"的Windows Terminal

    前言 在一年一度的微软开发者大会Build 2019登场的Windows Terminal饱受好评,大家对其也是充满了兴趣和热情,程序员的朋友圈都被微软发布的最新终端 windows Terminal ...

  10. [Beta阶段]测试报告

    [Beta阶段]测试报告 博客目录 测试方法及过程 在正式发布前,为检验后端各接口功能的正确性,后端服务器对压力的耐受程度,以及前端各页面.功能的运行情况,我们对我们的服务器及小程序进行了多种测试.除 ...