python 3.x 的装饰器笔记

  今天学到了python的装饰器,感觉这个东西还是稍微有些复杂,所以记录下来,方便以后的查找。虽然标题是python 3.x的装饰器,但是我也没有怎么用过python 2.x,感觉上应该是和python 2.7在用法上差不多。

  现在某个视频公司有一段代码,,代码的主要功能就是看电影。

1 def watchfilm():
2     print(‘You are watching film now....‘)
3
4 watchfil()

  运行之后输出:

You are watching film now....

  现在要求来了,老板提出看电影之前必须要进行登录。

  此时小A想到开放封闭原则,原有的代码不能更改,但是需要进行扩展。于是小A有了以下想法:

    1.可以定义一个登录函数,将看电影函数的内存地址作为参数传入

    2.运行登录函数,将原先看电影函数的内存地址返回

    3.使用新的变量存储原先看电影函数的内存地址,将新变量和原先看电影函数的函数名定义为相同的名字

    4.运行新变量的时候就就会找到内存地址,运行原先看电影函数的代码

  基于以上想法,小A写出了如下代码:

1 def login(func):
2     print(‘username&password verification....‘)
3     return func
4
5 def watchfilm():
6     print(‘You are watching film now....‘)
7
8 watchfilm=login(watchfilm)
9 watchfilm()

  运行之后输出:

username&password verification....
You are watching film now....

  老板看后很满意,然后说:不行!

  因为看电影函数是基础平台,而调用是业务部门再进行调用,如果这样修改,就需要业务部门修改大量的代码。

  方案被老板否定了,但是活还得接着干啊。小A一筹莫展。

  某一天,小A遇见了小B,向小B倾诉了自己的苦恼,小B说道:“使用python的装饰器啊。”

  小B解释到,装饰器实现的东西和你做的东西是一样的,不过装饰器使用语法糖@来装饰函数。装饰器执行时,把被装饰函数的内存作为参数传给装饰器,同时执行装饰器函数,最后返回新定义的函数名,和被装饰的函数名相同,只不过内存地址可不一定就是被装饰的函数的内存地址了。再执行被装饰函数时,其实执行的是新的函数。

  小A一听,有门,来了精神。经过了一段时间的研究,于是有了一下代码:

1 def login(func):
2     print(‘username&password verification....‘)
3     return func
4
5 @login
6 def watchfilm():
7     print(‘You are watching film now....‘)
8
9 watchfilm()

  运行之后输出:

username&password verification....
You are watching film now....

  能够满足要求,小A顿时兴奋起来。小A马上又测试了几次,没有问题。就在小A想着可以交差的时候,他发现了一个问题。

 1 def login(func):
 2     print(‘username&password verification....‘)
 3     return func
 4
 5 @login
 6 def watchfilm():
 7     print(‘You are watching film now....‘)
 8
 9 print(‘other operation.....‘)
10 watchfilm()

  运行之后输出:

username&password verification....
other operation.....
You are watching film now...

  明明没有调用函数,为什么会有输出呢?登录程序应该是在其它操作之后,看电影之前才对啊?小A看了看程序,马上明白了问题所在,因为程序只要启动,就会执行装饰器函数,执行装饰器函数就会执行登录程序,导致了现在这种情况。

  这样不行啊,怎么才能解决呢?

  忽然小A灵机一动,想到了一个办法,于是有了代码2.0

 1 def login(func):
 2     def inner():
 3         print(‘username&password verification....‘)
 4         func()
 5     return inner
 6
 7 @login
 8 def watchfilm():
 9     print(‘You are watching film now....‘)
10
11 print(‘other operation.....‘)
12 watchfilm()

  运行之后输出:

other operation.....
username&password verification....
You are watching film now....

  完美解决了问题,小A长出了一口气。

  第二天,小A赶紧找到老板,说出了自己的想法。

  老板满意的点点头,对小A说道:你做的很好,但是现在咱们需求变了,目前还想在看电影之前放一段广告而且看完电影之后推荐几部电视节目,你看咱们能不能实现一下。

  小A虎躯一震,擦了擦头上的汗,点头应承了下来。但是小A此时也犯了难,如何使用装饰器进行实现呢?小A想到了小B,于是赶紧去请教小B,一顿酒肉计下来,小B跟小A说,你想想装饰器的原理,如果我在有一层def呢?小A一拍大腿,对啊,我怎么没有想到。

  小A赶紧进行设计,于是有了代码3.0

 1 def advert():
 2     print(‘advertisement time...‘)
 3
 4 def recommend():
 5     print(‘recommend TV show...‘)
 6
 7 def login(adv,rec):
 8     def inner(func):
 9         def inner2():
10             print(‘username&password verification....‘)
11             adv()
12             func()
13             rec()
14         return inner2
15     return inner
16
17 @login(advert,recommend)
18 def watchfilm():
19     print(‘You are watching film now....‘)
20
21 print(‘other operation.....‘)
22 watchfilm()

  运行之后输出:

other operation.....
username&password verification....
advertisement time...
You are watching film now....
recommend TV show...

  装饰器带参数之后会首先运行带参数的函数,本例中是login(advert,recommend),函数返回inner函数的内存地址,之后装饰器开始执行,就会变成执行@inner装饰器,之后因为之前两个函数已经传入过,所以再调用函数的时候就能显示输出了。

  小A很高兴,这次真是又快又好的完成了任务,于是他唯恐事件有变,赶在老板下班之前向老板进行了汇报。

  老板听了小A的汇报相当满意,高声称赞小A,忽然话锋一转,说道:但是小A啊,咱们的需求现在。。。。。。。

  (未完待续)

时间: 2024-11-25 16:19:31

python 3.x 的装饰器笔记的相关文章

python高级编程之装饰器04

from __future__ import with_statement # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' #with和contextlib #对于要确保即使发生一个错误时也能运行一些清理代码而言,try...finally语句很有用,对以下场景,如: """ 关闭一个文件, 释放一个锁 创建一个临时代码补丁 在特殊环境中运行受保护代码 ----------- with语句覆盖

Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化

本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 先定义一个基本的装饰器: ########## 基本装饰器 ########## def orter(func):    #定义装饰器     de

Python学习之路-装饰器&生成器&正则表达式

装饰器 通俗的讲,装饰器就是在不改变源代码基础上,给源代码增加新功能. 不改变函数的源代码.调用方式.返回值等,给函数增加新功能. 经典案例:登录装饰器, def login_decorator(func):     def inner():         if USER_TEMP["status"] == False:             print("\033[31;1m用户未登录,请先登录\033[0m")             login_atm()

python高级编程之装饰器02

#装饰器02 #参数检查 #主要是用在接收或者返回函数,在特定上下文执行时可能有用 #例如:有一个函数通过XML-RPC调用,python将不能和静态类语言中一样直接提供它的完整签名,当XML-RPC客户要求函数签名时,就需要这样的能力 """ xml-rpc相关学习:http://zh.wikipedia.org/wiki/XML-RPC """ #装饰器能提供这种签名类型,并确保输入输出与此有关,如下 from itertools impor

python高级编程之装饰器01

# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' #装饰器01 #特点是:使得函数和方法封装(接收一个函数并返回增强版本一个函数) #语法:原始场景可以将方法 在定义首部将其定义为类方法或者静态方法,在未使用装饰器之前,语法如下: class WhatFort(object): def it(cls): print 'work with %s:'%cls it=classmethod(it) def uncommo

Python 函数式编程、装饰器以及一些相关概念简介

Python 中的 Decorator(装饰器) 是对一个函数或者方法的封装,从而使其可以完成一些与自身功能无关的工作. 预备知识 一切皆对象 在 Python 中,所有的一切都被视为对象,任何的变量.函数.类等都是 object 的子类.因此除了变量之外,函数和类等也可以被指向和传递. >>> def foo(): ... pass ... >>> def Foo(): ... pass ... >>> v = foo >>> v

python 中多个装饰器的执行顺序

python 中多个装饰器的执行顺序: def wrapper1(f1): print('in wrapper1') def inner1(*args,**kwargs): print('in inner1') ret = f1(*args,**kwargs) return ret return inner1 def wrapper2(f2): print('in wrapper2') def inner2(*args,**kwargs): print('in inner2') ret = f2

Python函数编程——闭包和装饰器

Python函数编程--闭包和装饰器 一.闭包 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包.也就是说,内部函数会在外部函数返回后被执行.而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量.参数以及其他内部函数.这些局部变量.参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响. def outer(

python基础三大器之装饰器

闭包 由于闭包这个概念比较难以理解,尤其是初学者来说,相对难以掌握,所以我们通过示例去理解学习闭包. 给大家提个需求,然后用函数去实现:完成一个计算不断增加的系列值的平均值的需求. 例如:整个历史中的某个商品的平均收盘价.什么叫平局收盘价呢?就是从这个商品一出现开始,每天记录当天价格,然后计算他的平均值:平均值要考虑直至目前为止所有的价格. 比如大众推出了一款新车:小白轿车. 第一天价格为:100000元,平均收盘价:100000元 第二天价格为:110000元,平均收盘价:(100000 +