Python基础(八)装饰器
今天我们来介绍一下可以提升python代码逼格的东西——装饰器。在学习装饰器之前我们先来复习一下函数的几个小点,方便更好的理解装饰器的含义。
一、知识点复习
1, 在函数中f1和f1()有什么不同,f1:表示的是将整个函数看作一个整体;f1():表示执行f1函数,下面通过一个例子来看一下:
1
2
3
4
5
|
def f1(): print ( 'f1' ) f1 #代表函数体本身,什么也不操作 f1() #代表执行函数 |
2、lambda函数:
1
2
3
4
|
f1 = lambda f1:f1 + 100 print (f1( 50 )) 150 |
3、Python的从上到下的执行方式:
1
2
3
4
5
6
7
|
def f1(): #根据Python从上而下的原则,先将f1函数加载到内存 print ( 'f1' ) #指向print('f1'),当下面在出现f1函数时指针会指向 def f1(): #新的值,跟变量赋值的原理一样 print ( 'f2' ) f1() f2 |
二、装饰器
下面通过一个需求来介绍装饰器在代码中的应用和如何提高代码逼格,需求如下:
B市某创业公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作、redis调用、监控API等功能。业务部门使用基础功能时,只需要调用基础平台提供的功能即可。具体情况如下:
1
2
3
4
5
6
7
8
|
#基础部门提供的功能如下: def f1(): print ( 'f1' ) def f2(): print ( 'f2' ) def f3(): print ( 'f3' ) |
1
2
3
4
5
|
#其他业务部门调用的方法如下: f1() f2() f3() |
目前公司有条不紊的进行着,但是,以前基础平台的开发人员在写底层代码时没有关注验证相关的问题,即:基础平台的提供的功能可能被任何人使用。现在需要对基础平台的所有功能进行重构,为平台提供的所有功能添加验证机制,即:执行功能前,先进行验证。
现在老大把工作交给了小明,他是这么做的:
1
|
小明本身比较low,于是去找每个业务部门交涉,每个业务部门自己写代码,调用基础平台的功能之前先验证,这样基础平台就不用修改代码了。 |
当天小明就被开除了,老大语重心长的说回去好好学学Python吧。
老大又把活交给小明2号 ,小明2号比小明要聪明一点,心想傻X才会一个部门一个部门去找呢,于是重构了基础平台的代码,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#基础平台代码: def f1(): #验证 print ( 'f1' ) def f2(): #验证 print ( 'f2' ) def f3(): #验证 print ( 'f3' ) #其他业务部门调用基础平台代码不变: f1() f2() f3() |
就这样小明2号修改了一周交差了,然而命运总是这么爱捉弄人,几个部门开会说加验证太麻烦,要去掉,又交给了小明2号,这次老大给了排期,一天之内做完,小明2号懵逼了,跟老大说完不成,于是老大去看了小明2号的修改的代码,然后就没有然后了,小明2号也光荣的退出了历史舞台。
经过两次以后,老大已经下定决心要招个牛逼的Python开发,广发英雄帖请来了小明3号,将上面的工作交给了他,下面来看看小明3号是如何修改的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#基础平台提供的功能如下: def check_login(): #验证 pass def f1(): check_login() print ( 'f1' ) def f2(): check_login() print ( 'f2' ) ... #其他业务部门调用方法不变: f1() f2() ... |
修改完以后,老大看完代码很欣慰,对小明3号说:
写代码要遵循开发封闭的原则,虽然在这个原则是用在面向对象开发,但是也适用于函数式编程,简单来说,规定已经实现的功能代码不允许被修改,但可以被扩展,即:
⊙封闭:已经实现的功能代码块
⊙开放:对扩展开放
如果将开放封闭原则应用在上述需求中,那么就不允许在函数f1、f2、f3的内部进行修改代码,老大说现在给你一个举个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
def outer(func): def inner(): #check1 #check2 return func() return inner @outer def f1(): print ( 'f1' ) @outer def f2(): print ( 'f2' ) ... |
上述代码,也是仅仅对基础平台代码进行修改,就可以实现在其他人调用函数f1、f2、f3之前都进行[验证]操作,并且其他业务部门无需做任何操作。
小明3号有点疑惑的问,这段代码的内部执行原理是什么呢?
老大说想知道,晚上洗干净等着我,这时小明3号菊花一紧,我X,老大还有这癖好,老大:逗你的,实际内部实现很简单,下面给你讲一下:
单独以f1为例:
1
2
3
4
5
6
7
8
9
10
|
def outer(func): def inner(): #check #check return func() return inner @outer def f1(): print ( 'f1' ) |
当写完这段代码后(函数未被执行),Python解释器会从上到下解释代码,步骤如下:
1,def outer(func): 将outer函数加载到内存
2,@outer 调用装饰器
从表面上看解释器仅仅会解释两句代码,因为函数在没有被调用之前其内部代码不会被执行,但是
@outer这句代码里却大有文章。
@函数名是Python的一种语法糖:
1,执行outer函数并将@outer下面的函数作为outer函数的参数,即:@outer 就等价于outer(f1)。
1
2
3
4
5
6
7
|
def inner(): #check return f1() #fun是参数,此时就相当于整个f1函数塞进了另一个函数中 return inner #返回inner,inner代表的是函数,而不是去执行inner函数 |
2,将执行完的outer函数返回值赋值给@outer下面的函数的函数名。
1
2
3
4
5
6
7
8
9
10
11
12
|
#outer的返回值为: def outer(func): def inner(): #check return f1() #此时的func已经是原来的f1函数 return inner #然后,将返回值在重新赋值给f1,即: 新f1 = def inner(): #check return f1() |
这样一来,以后业务部门想要执行f1函数时,就会执行新f1函数,在新f1函数内部先验证在执行原来的f1函数,再将原来f1函数的返回值返回给业务调用者。
老大:回去好好研究一下吧,不懂洗干净晚上来我家。。。。
三、装饰器参数
1、被装饰的函数有参数
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
|
#有一个参数时: def outer(func): def inner(args): #check1 #check2 return func(args) return inner @outer def f1(args): print ( 'f1' ) #有两个参数时: def outer(func): def inner(arg1,arg2): #check1 #check2 return func(arg1,arg2) return inner @outer def f1(arg1,arg2): print ('f1') #如果有多个参数怎么办,这里就用到了我们之前学的万能参数*args、**kwargs def outer(func): def inner( * args, * * kwargs): #check1 #check2 return func( * args, * * kwargs) return inner @outer def f1(arg1,arg2,arg3,arg4 ): print ('f1') |
2、一个函数被多个装饰器装饰
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
def outer1(func): def inner( * args, * * kwargs): #check1 #check2 return func( * args, * * kwargs) return inner def outer2(func): def inner( * args, * * kwargs): #check1 #check2 return func( * args, * * kwargs) return inner @outer1 @outer2 def f1(arg1,arg2,arg3,arg4): print ( 'f1' ) |
3、双重装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
def Before(request,kargs): print ( 'before' ) def After(request,kargs): pow ( 'After' ) def Filter (brefore_func,after_func): def outer(main_func): def wrapper(request,kargs): brefore_result = brefore_func(request,kargs) if (brefore_result ! = None ): return brefore_result main_result = main_func(request,kargs) if (main_result ! = None ): return main_result return wrapper return outer @Filter (Before,After) def Index(request,kargs): print ( 'index' ) |
Python基础(八)装饰器的更多相关文章
- python基础—函数装饰器
python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...
- 十. Python基础(10)--装饰器
十. Python基础(10)--装饰器 1 ● 装饰器 A decorator is a function that take a function as an argument and retur ...
- [python基础]关于装饰器
在面试的时候,被问到装饰器,在用的最多的时候就@classmethod ,@staticmethod,开口胡乱回答想这和C#的static public 关键字是不是一样的,等面试回来一看,哇,原来是 ...
- Day11 Python基础之装饰器(高级函数)(九)
在python中,装饰器.生成器和迭代器是特别重要的高级函数 https://www.cnblogs.com/yuanchenqi/articles/5830025.html 装饰器 1.如果说装 ...
- 1.16 Python基础知识 - 装饰器初识
Python中的装饰器就是函数,作用就是包装其他函数,为他们起到修饰作用.在不修改源代码的情况下,为这些函数额外添加一些功能,像日志记录,性能测试等.一个函数可以使用多个装饰器,产生的结果与装饰器的位 ...
- 学习PYTHON之路, DAY 5 - PYTHON 基础 5 (装饰器,字符格式化,递归,迭代器,生成器)
---恢复内容开始--- 一 装饰器 1 单层装饰器 def outer(func): def inner(): print('long') func() print('after') return ...
- python基础-----函数/装饰器
函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 函数的优点之一是,可以将代码块与主程 ...
- python基础之装饰器(实例)
1.必备 #### 第一波 #### def foo(): print 'foo' foo #表示是函数 foo() #表示执行foo函数 #### 第二波 #### def foo(): print ...
- 【Python基础】装饰器的解释和用法
装饰器的用法比较简单,但是理解装饰器的原理还是比较复杂的,考虑到接下来的爬虫框架中很多用到装饰器的地方,我们先来讲解一下. 函数 我们定义了一个函数,没有什么具体操作,只是返回一个固定值 请注意一下缩 ...
- Python基础之装饰器
1.什么是装饰器? Python的装饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的Decorator搞混了,其实这是完全不同的两个东西.虽然 ...
随机推荐
- Google Closure Compiler 高级模式及更多思考(转)
前言 Google Closure Compiler 是 Google Closure Tools 的一员,在 2009 年底被 Google 释出,早先,有 玉伯 的 Closure Compile ...
- java笔记线程电影院卖票改进版
通过加入延迟后,就产生了连个问题: * A:相同的票卖了多次 * CPU的一次操作必须是原子性的 * B:出现了负数票 * 随机性和延迟导致的 public class SellTicketD ...
- 用nginx进行同一个服务器下多域名的负载均衡配置
用nginx进行同一个服务器下多域名的负载均衡配置 Nginx进行http负载均衡的模块是upstream Upstream可以进行多个配置,这样的话可以灵活的配置站点,但是注意的是upstream后 ...
- (快速幂)51NOD 1046 A^B Mod C
给出3个正整数A B C,求A^B Mod C. 例如,3 5 8,3^5 Mod 8 = 3. Input 3个正整数A B C,中间用空格分隔.(1 <= A,B,C <= 10^ ...
- ACM_同余+暴力找规律
小光的忧伤 Time Limit: 2000/1000ms (Java/Others) Problem Description: 锴神:我尊重作者原意,你们出什么我就加什么.于是小光打了道水题(也就是 ...
- .net引用System.Data.SQLite操作SQLite
之所以要做这个笔记,是因为在.NET中使用System.Data.SQLite的时候,遇到了些问题,这些问题是相对于引用其他dll没有遇到过的,所以作个笔记,记录一下. 简单起见,首先建立一个控制台项 ...
- Spring-security配置代码
@Configuration public static class WebSecurityConfigurer extends WebSecurityConfigurerAdapter{ @Over ...
- 专题五:TCP编程
前言 前面专题的例子都是基于应用层上的HTTP协议的介绍, 现在本专题来介绍下传输层协议——TCP协议,主要介绍下TCP协议的工作过程和基于TCP协议的一个简单的通信程序,下面就开始本专题的正文了. ...
- hdu5122 K.Bro Sorting
思路: 模拟. 实现: #include <iostream> #include <cstdio> using namespace std; ], n, t; int main ...
- web安全测试--XSS(跨站脚本)与CSRF
XSS攻击原理 反射型 发出请求时,xss代码出现在URL中,作为输入提交到服务器端,服务器端解析后响应,xss代码随响应内容一起传回浏览器,最后浏览器解析执行xss代码.这个过程像一次反射,故叫反射 ...