Python核心编程 | 装饰器

装饰器是程序开发的基础知识,用好装饰器,在程序开发中能够提高效率

它可以在不需要修改每个函数内部代码的情况下,为多个函数添加附加功能,如权限验证,log日志等

涉及点:

1.先梳理一下

>>> def fun():
    print(‘Fun...‘)
# fun 是函数
# fun() 是执行函数

#A
>>> def test():
    print(1)
>>> def test():
    print(2)
#B
>>> test()
2
>>>

重复定义函数不会报错

只是会让函数名指向不同的函数体

>>> def test():
    print(‘TEST‘)
>>> def fun():
    print(‘FUN‘)
>>> test=fun # test改变指向,指向了和fun一样的函数体
>>> test()
FUN
>>>

在C和C++中,会告诉你两个函数重名了,在Python中不会,会默认改变指向

2.开放封闭原则

开放:对扩展开发

封闭:已实现的功能代码块

1.添加新需求,最好不要改动原来的代码块,因为别处已经调用的地方可能会报错,

尽可能进行扩展

2.开发的时候,别轻易删除代码

3.现有fun1,fun2函数,在每次调用这两个函数时,需要进行权限验证

>>> def fun1():
    print(‘fun1‘)

>>> def fun2():
    print(‘fun2‘)

>>> def test(fun):
    def inner():
      print(‘验证‘)
      fun()
    return inner

>>> mytest=test(fun1)
>>> mytest()
验证
fun1
>>>

不是直接在每个需要加验证的函数里面修改,那样违反了 开放封闭 原则

而是创建一个闭包:

test的参数在内部函数中被调用,被调用时,先执行验证功能。传入的参数决定了是哪个函数

所以即可以传入fun1,也可以传入fun2

上面的代码虽然添加了验证功能,在不改变原有代码部分的情况下。

但每次调用不是直接调用原来的fun1 、fun2;而是调用另一个函数

现在改变一下代码:

>>> def fun1():
    print(‘fun1‘)

>>> def fun2():
    print(‘fun2‘)

>>> def test(fun):
    def inner():
      print(‘验证功能‘)
      fun()
    return inner

>>> fun1=test(fun1) # 现在能够通过原有函数名直接调用,不改变原有函数代码

>>> fun1()

验证功能

fun1

>>>

如何解释上述代码?

其实只是改变了函数名对函数体的引用

执行fun1=test(fun1)时,test中的fun参数指向了fun1的函数体。inner中,执行了fun:fun()。现在让fun1改变它的指向,让它指向inner

所以调用fun1就是调用inner函数

简言之:通过改变引用,让inner函数里面既包含新功能,也包含了旧功能

然后改变原来函数名的指向,让它指向inner函数。

但是,每次都需要这么写:fun1=test(fun1) 过于麻烦

4.使用语法糖:

在fun1前面加 @test 等价于 fun1=test(fun1)

>>> def test(fun):
    def inner():
      print(‘验证功能‘)
      fun()
    return inner
>>> @test
  def fun1():
    print(‘fun1‘)
>>> fun1()
验证功能
fun1
>>>

装饰器:在原有的基础上,不改动原先代码,然后添加新的功能,进行装饰(Python特有)

5.例子

执行结果:

这类代码应该怎么看?

如14~16行代码,把test1的功能「给」makeBold里的fn

把执行test1当成执行makeBold里的wrapped函数

test3添加了两个装饰器,为什么结果是<b><i>hello world-3</i></b>

6.两个装饰器装饰过程:函数test3为例

装饰器@makeBold下面是装饰器@makeItalic,需要等装饰器@makeItalic将test3进行装饰之后

返回一个新的引用,再进行装饰,所以此时装饰器@makeBold没有被执行,先执行装饰器@makeItalic

1. @makeItalic:test3=makeItalic(test3) 此时test3指向新引用,makeItalic中的wrapped

[email protected]:test3=makeBold(test3)此时传入的test3为@makeItalic装饰后新的test3

此时,test3指向了@makeBold中的wrapped,@makeBold中的fn指向了@makeItalic中的wrapped,@makeItalic中的fn指向了原来test3的函数体。

倒着装,顺着执行

7.装饰器什么时候进行装饰?

在定义的时候就进行装饰,不是等到调用才装饰

>>> def fun(fn):
    print(‘正在装饰...‘)
      def inner():
      fn()
    return inner
>>> @fun
def test():
  print(‘函数‘)
正在装饰...
>>>

上述情况是没有参数的情况下进行

8.现在看一下有两个参数的情况

因为(原函数)test需要两个参数,所以在调用经过装饰器装饰的test时也要传入两个参数,

这两个参数经过inner,fn传入(原函数)test的函数体

但是,被装饰的函数形参发生变化时,都需要改变「装饰器」函数的形参吗

9.不定参数

使用不定参数,这样不管被装饰的函数形参怎么变化,装饰器会自动匹配,只需要更改被装饰的函数的代码就可以

如:

函数test的形参由2个增加到3个:

函数test的形参由3个改为没有:

10.被装饰的函数有返回值的情况

打印结果:None

由于fn()返回的结果没有被inner返回,所以打印test时为None

修改:

执行fn()时,执行的是第10行test里面的代码,返回了一个字符串,这个字符串,也就是fn的返回值

在inner被变量rn接收,inner又返回了变量rn。

11.通用装饰器

运行结果:

...

None

...

test2

...

vaule: 10

...

vaule: 10 20 30

通用的装饰器,同时满足了多种函数的情况,有无参、多参、有无返回值等

当函数没有返回值时,inner函数中的变量ret接收到None

inner的形参为*args、**kwargs为不定参

12.带参数的装饰器

原文地址:https://www.cnblogs.com/qiutenglong/p/10054214.html

时间: 2024-10-08 22:44:08

Python核心编程 | 装饰器的相关文章

Python 函数式编程--装饰器

1.1   装饰器 函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ...    print('2016') ... >>> now() 2016 >>> f = now    --函数对象赋值给变量 >>> f()     --调用 2016 函数对象的__name__,能拿到函数的名称 >>> now.__name__ 'now' >>> f.__name

python函数式编程-装饰器

由于函数也是一个对象,而且函数对象可以赋值给变量,所以通过变量也能调用该函数. >>> def now(): ... print('2015-3-25') ... >>> f=now >>> f <function now at 0x7f84f14fda28> >>> f() 2015-3-25 函数对象有一个__name__属性,可以拿到函数的名字 >>> f.__name__ 'now' >&g

Python核心编程的四大神兽:迭代器、生成器、闭包以及装饰器

生成器 生成器是生成一个值的特殊函数,它具有这样的特点:第一次执行该函数时,先从头按顺序执行,在碰到yield关键字时该函数会暂停执行该函数后续的代码,并且返回一个值:在下一次调用该函数执行时,程序将从上一次暂停的位置继续往下执行. 通过一个例子来理解生成器的执行过程.求1-10的所有整数的立方并将结果打印输出,正常使用列表的实现如下: 输出结果如下: 当数据量很少时,可以很快得到结果.但是如果范围扩大到10000甚至是100000000,就会发现程序执行时间会变长,变卡,甚至有可能会因超出内存

python核心编程--笔记

python核心编程--笔记 的解释器options: 1.1 –d   提供调试输出 1.2 –O   生成优化的字节码(生成.pyo文件) 1.3 –S   不导入site模块以在启动时查找python路径 1.4 –v   冗余输出(导入语句详细追踪) 1.5 –m mod 将一个模块以脚本形式运行 1.6 –Q opt 除法选项(参阅文档) 1.7 –c cmd 运行以命令行字符串心事提交的python脚本 1.8 file   以给定的文件运行python脚本 2 _在解释器中表示最后

Python深入05 装饰器

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法或者类进行加工.在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果.相对于其它方式,装饰器语法简单,代码可读性高.因此,装饰器在Python项目中有广泛的应用. 装饰器最早在Python 2.5中出现,它最初被用于加工函数和方法这样

Python核心编程的四大神兽

本文将主要分为4大部分,分别介绍Python核心编程中的迭代器.生成器 .闭包以及装饰器. 生成器 生成器是生成一个值的特殊函数,它具有这样的特点:第一次执行该函数时,先从头按顺序执行,在碰到yield关键字时该函数会暂停执行该函数后续的代码,并且返回一个值:在下一次调用该函数执行时,程序将从上一次暂停的位置继续往下执行. 通过一个例子来理解生成器的执行过程.求1-10的所有整数的立方并将结果打印输出,正常使用列表的实现如下: def lifang_ls(): """求1-1

ZMAN的学习笔记之Python篇:装饰器

年前工作事务比较繁琐,我只能用零碎的时间继续学习Python,决定开一个系列的博文,作为自己深入学习Python的记录吧.名字也取好了,就叫<ZMAN的学习笔记之Python篇>~开篇是关于装饰器的,春节假期码的字哈哈~就让我们开始吧! 本文的例子都是自己想的,如果不是很合适,请大家提出宝贵意见哈~谢谢啦! 一.为什么要用“装饰器” 比如我们写了如下一段代码: # 打印0~99 def func(): for i in range(100): print(i) 我们想要监测执行这个函数花费了多

[python基础]关于装饰器

在面试的时候,被问到装饰器,在用的最多的时候就@classmethod ,@staticmethod,开口胡乱回答想这和C#的static public 关键字是不是一样的,等面试回来一看,哇,原来是这样,真佩服我当时厚着脸皮回答的那些问题... OK,先来张图看看装饰器内容: OK,我们留下一个印象,然后我们看实际的场景来操作. 我们先看一个方法: __author__ = 'bruce' def do_sth(): print 'some thing has been done' if __

《Python核心编程》手记 基础

春节终于over了,回归充实的学习研究生活.打开久违的CSDN博客,看到官方推送的 『博客Markdown编辑器上线啦』,让我顿时有了写作的欲望,真是程序员的福利.之前阅读各种文章书籍,都是用MarkDownPad做的笔记,喜欢以及习惯于MarkDown简洁的语法. 总之各种方便.为了试试效果,将以前阅读<Python核心编程>的手记整理发上来,也当温习一遍. 第三章 Python基础 1.语句和语法 注释 Python中注释用符号"#",也可以用三引号:"' 注