1.认识装饰器

  如果你经常看我的博客,你已经学会了python的前两大‘神器’(迭代器,生成器),那么什么是装饰器呢?就如字面意义装饰器是对某个事物(通常指函数)进行装饰,让其在不修改任何内部代码的情况下增添新的功能,接下来我将一步步的解析python的装饰器。

2.闭包

  在解析装饰器之前我们需要先了解下闭包的概念,我们先通过一段代码了解闭包

# 定义一个函数
def test(number): # 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
def test_in(number_in):
print("in test_in 函数, number_in is %d" % number_in)
return number+number_in
# 其实这里返回的就是闭包的结果
return test_in # 给test函数赋值,这个20就是给参数number
ret = test(20) # 注意这里的100其实给参数number_in
print(ret(100)) #注 意这里的200其实给参数number_in
print(ret(200))

 运行结果

in test_in 函数, number_in is 100
120 in test_in 函数, number_in is 200
220

看完这段代码我们不妨总结下闭包的作用:  

  1.函数名只是函数代码空间的引用,当函数名赋值给一个对象的时候 就是引用传递

  2.闭包就是一个嵌套定义的函数,在外层运行时才开始内层函数的定义,然后将内部函数的引用传递函数外的对象

  3.内部函数和使用的外部函数提供的变量构成的整体称为闭包

3.初识装饰器

  为什么在解释装饰器时要先了解闭包的概念呢?看完下面的代码你也会就会明白

def decorate(func):
def inner(): return "<i>"+func()+"</i>" return inner @decorate
def func():
return "你好" print(func())

 运行结果

<i>你好</i>

  我们可以看出装饰器就是在闭包的基础上做了一些修改。

4.装饰器普通传参

from time import ctime, sleep

def timefun(func):
def wrapped_func(a, b):
print("%s called at %s" % (func.__name__, ctime()))
print(a, b)
func(a, b)
return wrapped_func @timefun
def foo(a, b):
print(a+b) foo(3,5)
sleep(2)
foo(2,4)

运行结果

foo called at Thu Aug 23 21:30:21 2018
3 5
8
foo called at Thu Aug 23 21:30:23 2018
2 4
6

5.装饰器不定长传参

from time import ctime, sleep

def timefun(func):
def wrapped_func(*args, **kwargs):
print("%s called at %s"%(func.__name__, ctime()))
func(*args, **kwargs)
return wrapped_func @timefun
def foo(a, b, c):
print(a+b+c) foo(1,2,3)
sleep(1)
foo(4,5,6)

运行结果

foo called at Thu Aug 23 21:32:50 2018
6
foo called at Thu Aug 23 21:32:51 2018
15

 其实这里只是运用了python函数传参时的不定长传参的概念 

6.装饰器中的return

from time import ctime, sleep

def timefun(func):
def wrapped_func():
print("%s called at %s" % (func.__name__, ctime()))
func()
return wrapped_func @timefun
def foo():
print("I am foo") @timefun
def getInfo():
return '----hahah---' foo()
sleep(2)
foo() print(getInfo())

 运行结果

foo called at Thu Aug 23 21:36:22 2018
I am foo
foo called at Thu Aug 23 21:36:24 2018
I am foo
getInfo called at Thu Aug 23 21:36:24 2018
None

7.装饰器工厂(flask定义一个路由的方式)

from time import ctime, sleep

def timefun_arg(pre="hello"):
def timefun(func):
def wrapped_func():
print("%s called at %s %s" % (func.__name__, ctime(), pre))
return func()
return wrapped_func
return timefun @timefun_arg("php")
def foo():
print("I am foo") @timefun_arg("python")
def too():
print("I am too") foo()
sleep(2)
foo() too()
sleep(2)
too()

运行结果

foo called at Thu Aug 23 21:40:34 2018 php
I am foo
foo called at Thu Aug 23 21:40:36 2018 php
I am foo
too called at Thu Aug 23 21:40:36 2018 python
I am too
too called at Thu Aug 23 21:40:38 2018 python
I am too

  

 

我们分析下装饰器工厂装饰过程
  1. 调用timefun_arg("itcast")
    2. 将步骤1得到的返回值,即time_fun返回, 然后time_fun(foo)
    3. 将time_fun(foo)的结果返回,即wrapped_func

  4. 让foo = wrapped_fun,即foo现在指向wrapped_func

8.类装饰器

class Test(object):
def __init__(self, func):
print("初始化中....")
print("func name is %s"%func.__name__)
self.__func = func
def __call__(self):
print("装饰中......")
self.__func() @Test
def test():
print("----test---")
test()

运行结果

初始化中....
func name is test
装饰中......
----test---

我们也许会发现装饰器中有个很特别的方法__call__(),这个方法时python内置的魔法方法,它作用就是让类能够向函数一样直接被调用,接下来我会专门更新一篇python中的魔法方法,如果想要了解的朋友可以关注我

总结

 1.装饰器函数只有一个参数就是被装饰的函数的应用

  2.装饰器能够将一个函数的功能在不修改代码的情况下进行扩展

  3.在函数定义的上方@装饰器函数名 即可直接使用装饰器对下面的函数进行装饰。

 

python三大神器===》装饰器的更多相关文章

  1. Python三大器之装饰器

    Python三大器之装饰器 开放封闭原则 一个良好的项目必定是遵守了开放封闭原则的,就比如一段好的Python代码必定是遵循PEP8规范一样.那么什么是开放封闭原则?具体表现在那些点? 开放封闭原则的 ...

  2. python基础(补充):python三大器之装饰器

    函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_sum(*args): i = ...

  3. python三大器之装饰器的练习

    装饰器 加载顺序从下至上 执行顺序从上至下 ''' 多层装饰器 ''' def deco1(func): #func=deco2 def wrapper1(*args, **kwargs): '''t ...

  4. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  5. [python基础]关于装饰器

    在面试的时候,被问到装饰器,在用的最多的时候就@classmethod ,@staticmethod,开口胡乱回答想这和C#的static public 关键字是不是一样的,等面试回来一看,哇,原来是 ...

  6. python笔记 - day4-之装饰器

                 python笔记 - day4-之装饰器 需求: 给f1~f100增加个log: def outer(): #定义增加的log print("log") ...

  7. Python深入05 装饰器

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法 ...

  8. Python 三大神器

    Python 三大神器 Python 中有很多优秀的包,本文主要讲一下 pip, virtualenv, fabric 1. pip 用来包管理 文档:https://pip.pypa.io/en/l ...

  9. Day04 - Python 迭代器、装饰器、软件开发规范

    1. 列表生成式 实现对列表中每个数值都加一 第一种,使用for循环,取列表中的值,值加一后,添加到一空列表中,并将新列表赋值给原列表 >>> a = [0, 1, 2, 3, 4, ...

  10. Noah的学习笔记之Python篇:装饰器

    Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) ...

随机推荐

  1. JDBC 存储过程

    存储过程 DROP PROCEDURE IF EXISTS `addUser`; CREATE PROCEDURE `addUser` (),in birthday date,in money flo ...

  2. Centos7 配置subversion

    CentOS7:配置SVN服务器 Posted on 2016-11-10 15:17 eastson 阅读(4266) 评论(0) 编辑 收藏 1. 安装 CentOS通过yum安装subversi ...

  3. 8年经验面试官详解 Java 面试秘诀

      作者 | 胡书敏 责编 | 刘静 出品 | CSDN(ID:CSDNnews) 本人目前在一家知名外企担任架构师,而且最近八年来,在多家外企和互联网公司担任Java技术面试官,前后累计面试了有两三 ...

  4. 分段控制器UISegmentedControl的使用、同一个控制器中实现多个View的切换、addChildViewController等方法的使用

    本文先讲解简单的分段控制器UISegmentedControl的使用,然后具体讲解它最常使用的场景:同一个控制器中实现多个View的切换. 文章构思: 1.先直接讲解一张UI效果图的四种实现方式. 2 ...

  5. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 按钮

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  6. c++实现线性表中的顺序表(数据结构课程作业)

    一.题目简介 实现顺序表的创建.初始化.赋值.插入.删除.按数据查找元素位置.按元素位置查找数据.清空.删除 的操作,以上操作用可用菜单选项完成 二.源程序代码 #include<iostrea ...

  7. Vue - @import css 加载第三方css

    @import '~@/assets/css/style.css' CSS loader 会把把非根路径的url解释为相对路径, 加~前缀才会解释成模块路径.

  8. Linux oracle 服务器清理缓存

    清理服务器缓存 echo 1 >/proc/sys/vm/drop_cachesecho 2 >/proc/sys/vm/drop_cachesecho 3 >/proc/sys/v ...

  9. Linux CentOS7 VMware 特殊权限set_uid、特殊权限set_gid、特殊权限stick_bit、软链接文件、硬连接文件

    一.特殊权限set_uid root用户本身拥有对/etc/passwd的写权限,无可厚非:那普通用户呢,这里就用到了setuid,setuid的作用是“让执行该命令的用户以该命令拥有者的权限去执行” ...

  10. PHP+MySQL实现在线测试答题实例

    这个实例主要给大家介绍如何使用jQuery+PHP+MySQL来实现在线测试题,包括动态读取题目,答题完毕后台评分,并返回答题结果. 读取答题列表: $sql = "select * fro ...