1.什么是装饰器

装饰器实际上就是为了给某程序增添功能,但该程序已经上线或已经被使用,那么就不能大批量的修改源代码,这样是不科学的也是不现实的,因为就产生了装饰器,使得其满足:

不能修改被装饰的函数的源代码

不能修改被装饰的函数的调用方式

满足1、2的情况下给程序增添功能

2.装饰器的组成

<函数+实参高阶函数+返回值高阶函数+嵌套函数+语法糖 = 装饰器 >

3.一切皆对象

首先我们来理解下 Python 中的函数:

def hi(name="yasoob"):

return "hi " + name

print(hi())

# output: 'hi yasoob'

# 我们甚至可以将一个函数赋值给一个变量,比如

greet = hi

# 我们这里没有在使用小括号,因为我们并不是在调用hi函数

# 而是在将它放在greet变量里头。我们尝试运行下这个

print(greet())

# output: 'hi yasoob'

# 如果我们删掉旧的hi函数,看看会发生什么!

del hi

print(hi())

#outputs: NameError

print(greet())

#outputs: 'hi yasoob'

在函数中定义函数:

def hi(name="yasoob"):

print("now you are inside the hi() function")

def greet():

return "now you are in the greet() function"

def welcome():

return "now you are in the welcome() function"

print(greet())

print(welcome())

print("now you are back in the hi() function")

hi()

#output:now you are inside the hi() function

# now you are in the greet() function

# now you are in the welcome() function

# now you are back in the hi() function

# 上面展示了无论何时你调用hi(), greet()和welcome()将会同时被调用。

# 然后greet()和welcome()函数在hi()函数之外是不能访问的,比如:

greet()

#outputs: NameError: name 'greet' is not defined

从函数中返回函数:

def hi(name="yasoob"):

def greet():

return "now you are in the greet() function"

def welcome():

return "now you are in the welcome() function"

if name == "yasoob":

return greet

else:

return welcome

a = hi()

print(a)

#outputs:

#上面清晰地展示了`a`现在指向到hi()函数中的greet()函数

#现在试试这个

print(a())

#outputs: now you are in the greet() function

在if和else后面返回的是greet 和 welcome,而不是 greet() 和 welcome()。为什么那样?这是因为当你把一对小括号放在后面,这个函数就会执行;然而如果你不放括号在它后面,那它可以被到处传递,并且可以赋值给别的变量而不去执行它

将函数作为参数传给另一个函数:

def hi():

return "hi yasoob!"

def doSomethingBeforeHi(func):

print("I am doing some boring work before executing hi()")

print(func())

doSomethingBeforeHi(hi)

#outputs:I am doing some boring work before executing hi()

# hi yasoob!

4.编辑第一个装饰器

创建第一个装饰器:

def a_new_decorator(a_func):

def wrapTheFunction():

print("I am doing some boring work before executing a_func()")

a_func()

print("I am doing some boring work after executing a_func()")

return wrapTheFunction

def a_function_requiring_decoration():

print("I am the function which needs some decoration to remove my foul smell")

a_function_requiring_decoration()

#outputs: "I am the function which needs some decoration to remove my foul smell"

a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)

#now a_function_requiring_decoration is wrapped by wrapTheFunction()

a_function_requiring_decoration()

#outputs:I am doing some boring work before executing a_func()

# I am the function which needs some decoration to remove my foul smell

# I am doing some boring work after executing a_func()

如上代码所示,它们封装一个函数,并且用这样或者那样的方式来修改它的行为。现在你也许疑惑,我们在代码里并没有使用 @ 符号?那只是一个简短的方式来生成一个被装饰的函数。这里是我们如何使用 @ 来运行之前的代码:

@a_new_decorator

def a_function_requiring_decoration():

"""Hey you! Decorate me!"""

print("I am the function which needs some decoration to "

"remove my foul smell")

a_function_requiring_decoration()

#outputs: I am doing some boring work before executing a_func()

# I am the function which needs some decoration to remove my foul smell

# I am doing some boring work after executing a_func()

#the @a_new_decorator is just a short way of saying:

a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)

如果我们运行如下代码会存在一个问题:

print(a_function_requiring_decoration.__name__)

# Output: wrapTheFunction

Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。我们修改上一个例子来使用functools.wraps:

from functools import wraps

def a_new_decorator(a_func):

@wraps(a_func)

def wrapTheFunction():

print("I am doing some boring work before executing a_func()")

a_func()

print("I am doing some boring work after executing a_func()")

return wrapTheFunction

@a_new_decorator

def a_function_requiring_decoration():

"""Hey yo! Decorate me!"""

print("I am the function which needs some decoration to "

"remove my foul smell")

print(a_function_requiring_decoration.__name__)

# Output: a_function_requiring_decoration

5.我的第一个装饰器

from functools import wraps

def decorator_name(f):

@wraps(f)

def decorated(*args, **kwargs):

if not can_run:

return "Function will not run"

return f(*args, **kwargs)

return decorated

@decorator_name

def func():

return("Function is running")

can_run = True

print(func())

# Output: Function is running

can_run = False

print(func())

# Output: Function will not run

注意:@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

6.使用场景

授权(Authorization):

from functools import wraps

def requires_auth(f):

@wraps(f)

def decorated(*args, **kwargs):

auth = request.authorization

if not auth or not check_auth(auth.username, auth.password):

authenticate()

return f(*args, **kwargs)

return decorated

日志(Logging):

from functools import wraps

def logit(func):

@wraps(func)

def with_logging(*args, **kwargs):

print(func.__name__ + " was called")

return func(*args, **kwargs)

return with_logging

@logit

def addition_func(x):

"""Do some math."""

return x + x

result = addition_func(4)

# Output: addition_func was called

在函数中嵌入装饰器:

from functools import wraps

def logit(logfile='out.log'):

def logging_decorator(func):

@wraps(func)

def wrapped_function(*args, **kwargs):

log_string = func.__name__ + " was called"

print(log_string)

# 打开logfile,并写入内容

with open(logfile, 'a') as opened_file:

# 现在将日志打到指定的logfile

opened_file.write(log_string + ' ')

return func(*args, **kwargs)

return wrapped_function

return logging_decorator

@logit()

def myfunc1():

pass

myfunc1()

# Output: myfunc1 was called

# 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串

@logit(logfile='func2.log')

def myfunc2():

pass

myfunc2()

# Output: myfunc2 was called

# 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串

python装饰器详解-学习笔记-Python装饰器详解相关推荐

  1. python资源管理器安装_Python学习笔记-Python安装

    Python安装 文章简介:本文介绍在不同操作系统中搭建Python编程环境. 一 搭建编程环境 在不同的操作系统中,Python存在细微的区别,下面介绍两个主要的Python版本. 1.1 Pyth ...

  2. python程序运行键_python学习笔记-python程序运行

    小白初学python,写下自己的一些想法.大神请忽略. 安装python编辑器,并配置环境(见http://www.cnblogs.com/lynn-li/p/5885001.html中 python ...

  3. [转载] Python学习笔记——用装饰器decorator和Memoization记忆化提高效率,原理讲清楚了

    参考链接: 在Python中使用装饰器进行记忆 Python学习笔记--用装饰器decorator和Memoization记忆化提高效率 装饰器Memoization记忆化运用`functools`中 ...

  4. TCP/IP详解学习笔记-基本概念

    为什么会有TCP/IP协议 在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别.就好像圣经中上帝打乱了各地人的口音,让他们无法合作一样 ...

  5. python __name__怎么使用_python学习笔记26(python中__name__的使用)

    在python中,每个py文件都是一个模块,也都是一个可执行文件,即包含main方法.因此,对每个py文件,可以单独运行,也可以import它给其他客户使用,这两种情况不一样. 1. 如果模块是被导入 ...

  6. 基础才是王道——TCP/IP详解学习笔记 这位仁兄写得太好了

    TCP/IP详解学习笔记 这位仁兄写得太好了 TCP/IP详解学习笔记   这位仁兄写得太好了. http://blog.csdn.net/goodboy1881/category/204448.as ...

  7. VC++深入详解学习笔记

    VC++深入详解学习笔记 Lesson1: Windows程序运行原理及程序编写流程 Lesson2: 掌握C++基本语法 Lesson3: MFC框架程序剖析 Lesson4: 简单绘图 Lesso ...

  8. TCP/IP详解学习笔记(1)-基本概念

    为什么会有TCP/IP协议 在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别.就好像圣经中上帝打乱了各地人的口音,让他们无法合作一样 ...

  9. TCP_IP详解学习笔记

    TCP/IP详解学习笔记(1)-基本概念 为什么会有TCP/IP协议 在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别.就好像圣经中 ...

最新文章

  1. java 线程池 初始大小,Java线程池ThreadPoolExecutor的实现和参数
  2. python 日志模块 logging
  3. 27.垃圾收集器(Serial收集器、ParNew收集器、Parallel收集器、Parallel Old 收集器、CMS收集器、G1收集器、常用的收集器组合)
  4. 解决 锁定文件失败 打不开磁盘“D:\ubuntu\Ubuntu 64 位.vmdk”或它所依赖的某个快照磁盘。 模块 Disk”启动失败...
  5. 模型稳定后放在服务器上,把工程放在服务器上
  6. Java SimpleTimeZone toString()方法与示例
  7. 简述计算机进行远程桌面管理操作过程,服务器应用之“远程桌面连接”(操作篇)...
  8. 学习Windows Mobile开发系列笔记(win32基本程序框架)
  9. (一)UI设计的一些常识
  10. 【stm32开发日志】步进电机、直线模组、丝杆的接线、编程与使用
  11. 基于车载以太网的音视频传输 AVB vs RTP
  12. Protobuf协议格式详解
  13. javac不是内部或外部命令,也不是可运行的程序 或批处理文件的细节问题(window10)
  14. 【FI】财务预制凭证界面隐藏过账按钮
  15. PCB板材及叠层结构
  16. java hssffont_Java HSSFFont.setColor方法代碼示例
  17. 单片机通过mqtt联网(51单片机和esp01s)
  18. 网络技术摘抄(入门需知)
  19. C# 打印照片和文档
  20. c语言有趣代码,分享一段有趣的小代码

热门文章

  1. android内容提供器读取图片,android实现拍照或从相册选取图片
  2. Ubuntu里面vi编辑器在编辑文本时 如何在所有行行首或行尾插入字符
  3. 关于渐变属 gradient:
  4. 《DSP using MATLAB》示例Example 8.5
  5. prototype小解
  6. C++初始化,之不明白篇 coutxendl 与 coutx = coutxendl的输出的值会不一样...
  7. Android 应用程序基础(Application Fundamentals)
  8. 智能移动项目打包发布经验交流
  9. UVA10191 Longest Nap【排序】
  10. UVA11661 Burger Time?【文本处理】