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. Ubuntu12.04LTS中安装和使用Spin

    https://blog.csdn.net/jackandsnow/article/details/94434481 把第三步 安装tk(在wish中):apt-get install wish 改为 ...

  2. Microsoft Cortana移动版除美国市场外不再可用

    导读 先前已经透露,Microsoft Cortana的移动版本已不复存在.目前,Microsoft Cortana在移动设备上的多个国家和地区中支持多种语言.微软的Cortana移动版本不再支持的市 ...

  3. 「SDOI2009」HH的项链

    「SDOI2009」HH的项链 传送门 数据加强了,莫队跑不过了. 考虑用树状数组. 先把询问按右端点递增排序. 然后对于每一种贝壳,我们都用它最右一次出现的位置计算答案. 具体细节看代码吧. 参考代 ...

  4. 「CH6202」黑暗城堡

    「CH6202」黑暗城堡 传送门 这道题是要让我们求以点 \(1\) 为源点的最短路树的方案数. 我们先跑一遍最短路,然后考虑类似 \(\text{Prim}\) 的过程. 当我们把点 \(x\) 加 ...

  5. 从系统引导菜单禁用Hyper-V

    1, 从当前引导运行的系统复制一个新引导菜单项: bcdedit /copy {current} /d "Win10 NO_HV" 这时候cmd会输出新引导项的 guid, 复制出 ...

  6. Scrapy 使用 LinkExtractor 提取链接和使用 Exporter 导出数据

    在爬取一个网站时,想要爬取的数据通常分布到多个页面中,每个页面包含一部分数据以及其他页面的链接,提取链接有使用 Selector 和使用 Linkextractor 两种方法. 1.使用Selecto ...

  7. CF1209C Paint the Digits

    CF1209C Paint the Digits 题意:给定T组数据,每组数据第一行输入数字串长度,第二行输入数字串,用数字1和2对数字串进行涂色,被1涂色的数字子串和被2涂色的数字子串拼接成新的数字 ...

  8. jmeter分布式linux负载机,windows主控机

    1.将参数化文件上传到linux服务器,放在linux上jmeter的bin路径下 2.设置server.rmi.ssl.disable=true 分别修改主控机和负载机的jmeter.propert ...

  9. [转载]Spring下IOC容器和DI(依赖注入) @Bean及@Autowired

    Spring下IOC容器和DI(依赖注入) @Bean及@Autowired自动装配 bean是什么 bean在spring中可以理解为一个对象.理解这个对象需要换一种角度,即可将spring看做一门 ...

  10. SPringBootJPA的使用快速开发

    一文搞懂如何在 Spring Boot 中正确使用 JPA JPA 这部分内容上手很容易,但是涉及到的东西还是挺多的,网上大部分关于 JPA 的资料都不是特别齐全,大部分用的版本也是比较落后的.另外, ...