对于装饰器来说,就是在不改变函数的调用的情况下,对函数的前后增加了些许功能,这完全符合函数的 开放封闭 原则。装饰器的本质 其实就是一个闭包函数。

  这是一个装饰器的步骤图

def wrapper(func):  #
def inner(*args,**kwargs): #
ret = func(*args,**kwargs) #
return ret #
return inner # @wrapper #shopping = wrappers(shooping) # 1 --shopping = innner
def shopping(num): #
print(num) #
return 1 # print(shopping(5)) #

 

 

  这样你调 shopping 时, 真实情况是你在调用 inner 函数。如果 你想打印其函数名时打印的其实是 innner 函数。

from functools import wraps
def wrapper(func): #
@wraps(func)
def inner(*args,**kwargs): #
ret = func(*args,**kwargs) #
return ret #
return inner # @wrapper #shopping = wrappers(shooping) # 1 --shopping = innner
def shopping(num): #
print(num) #
return 1 # print(shopping(5)) #
print(shopping.__name__)  #以字符串的形式获取到函数名
print(shopping.__doc__)  #以字符串的形式获取到函数注释

  如果用内置的模块,wraps ,就可以轻松解决这个问题,使得所有的还和以前一样,其中wraps(),中要传入参数,参数应该与外层装饰器的形参一致。

  对于装饰器,如果你想取消个这装饰器的功能,现在给出的方法就只能是在装饰的外面在套一个装饰器,并设置一个定位符(一个全局变量)来控制其是否执行:

control = True
def outer(flag):
def wrapper(func):
def inner(*args,**kwargs):
if flag:
print('函数执行前')
ret = func(*args,**kwargs)
print('函数执行后')
return ret
else:
ret = func(*args, **kwargs)
return inner
return wrapper @outer(control)# shoping = outer(shopping) = wapper(shoping) = inner(shopping) 只是要多一个参数进行判断
def shopping(num):
print(num)
return 1 shopping(5)

  

  多个装饰器进行嵌套,装饰器的糖的运行是,就近原则,离函数最近的糖先运行

def wrapper1(func):  #func--shopping
def inner(*args,**kwargs):
print('000函数执行前')
ret = func(*args,**kwargs)
print('000函数执行后')
return ret
return inner def wrapper2(func):  #func--inner1
def inner(*args,**kwargs):
print('111函数执行前')
ret = func(*args,**kwargs)  #这里的调用其实是使用 inner1() 函数
print('111函数执行后')
return ret
return inner @wrapper2
@wrapper1
def shopping(num):
print(num)
return 1 shopping(5)
'''
111函数执行前
000函数执行前
5
000函数执行后
111函数执行后
'''

  来个作业

# 在12 天作业 编写装饰器,为多个函数加上认证功能(用户的账号来源于文件),
# 要求登入一次成功,后续的函数都无需再输入用户和密码
def wrapper(func):
def inner(*args, **kwargs):
with open('ver', mode='r+',encoding='utf-8')as f:
flag = f.read()
if flag:
verification = input('>>>').strip()
if verification == 'eli123':
# f.seek(0)
f.truncate(0,)
ret = func(*args, **kwargs)
return ret
else:
ret = func(*args, **kwargs)
return ret
return inner @wrapper
def buy(num):
print('买了{}个包子'.format(num))
@wrapper
def eat(num):
print('吃了{}个包子'.format(num))
with open('ver',mode='w',encoding='utf-8') as f:
f.write('aaa')
buy(3)
eat(2)

  这里利用了一个文件,在进行函数前,生成内容,然后文件中有内容时,要求验证 验证码,然后删除,方便第二次的验证。

# 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
from functools import wraps
def wrapper(func):
wraps(func)
def inner(*args, **kwargs):
with open('record',mode='a',encoding='utf-8') as f:
f.write(func.__name__ + '\n')
ret = func(*args, **kwargs)
return ret
return inner @wrapper
def buy(num):
print('买了{}个包子'.format(num))
@wrapper
def eat(num):
print('吃了{}个包子'.format(num)) buy(3)
eat(2)

  与第一题相比,确实比较容易一点(之后学到时间模块,可以加入时间模块的)

Python学习之路基础篇--11-12Python基础,函数的装饰器的更多相关文章

  1. python学习之路入门篇

    本文是up学习python过程中遇到的一些问题及总结归纳,本小节是入门篇. python基本语法 循环.分支不多赘述. 模块:一个.py文件就是一个模块. 文件和异常 模式 含义解释 “r” 读模式 ...

  2. python学习之路 八 :面向对象编程基础

    本节重点 了解面向对象.面向过程的区别 掌握什么是类,什么是对象 掌握如何定义及使用类和对象 了解类与对象间的关系 掌握类属性和实例属性 掌握绑定方法 一.编程范式 ​    ​编程即写程序or写代码 ...

  3. Python3基础(4)匿名函数、装饰器、生成器、迭代器、内置函数、json&pickle序列化、软件目录开发规范、不同目录间模块调用

    ---------------个人学习笔记--------------- ----------------本文作者吴疆-------------- ------点击此处链接至博客园原文------ 1 ...

  4. Python 学习之路 (一):基础

    数据类型和变量 整数 在Python3中,整数可以处理任意大小的整数,不分长整型和整型, 十六进制用0x开头或者H结尾表示:0x2af ,2afH 用函数 int() 来转换字符串中的数字,里面不能包 ...

  5. python学习之路---day25( 网络编程基础和初识socket)

    基本网络知识和初识socket一:基本知识 网线:传输电信号 集线器:将所有连接到集线器的网络设备连通起来 交换机: 升级版的集线器 网卡:接受电信号 MAC地址:物理地址: 8C-88-4B-88- ...

  6. python -- 返回函数、匿名函数、装饰器

    返回函数 高阶函数的参数可以是函数,那么其返回值也可以是函数. 闭包 对于高阶函数,内部函数可以引用外部函数的参数和局部变量.当调用外部函数返回内部函数时,相关参数和变量都保存在返回的函数(即内部函数 ...

  7. Python学习之路【第一篇】-Python简介和基础入门

    1.Python简介 1.1 Python是什么 相信混迹IT界的很多朋友都知道,Python是近年来最火的一个热点,没有之一.从性质上来讲它和我们熟知的C.java.php等没有什么本质的区别,也是 ...

  8. python学习之路基础篇(第四篇)

    一.课程内容回顾 1.python基础 2.基本数据类型  (str|list|dict|tuple) 3.将字符串“老男人”转换成utf-8 s = "老男人" ret = by ...

  9. python学习之路-day2-pyth基础2

    一.        模块初识 Python的强大之处在于他有非常丰富和强大的标准库和第三方库,第三方库存放位置:site-packages sys模块简介 导入模块 import sys 3 sys模 ...

  10. Python学习之路-Day1-Python基础

    学习python的过程: 在茫茫的编程语言中我选择了python,因为感觉python很强大,能用到很多领域.我自己也学过一些编程语言,比如:C,java,php,html,css等.但是我感觉自己都 ...

随机推荐

  1. css3 翻牌动画

    最近做了一个特效,css是从网上找的,地址是这个: CSS3 animate flip下的纸牌翻转效果实例页面 把其中核心的css代码扒出来如下: /* The properties in this ...

  2. C# Thread IsAlive 理解

    IsAlive的功能就是判断当前线程是否处于活动状态. public class Program { public static void Main(string[] args) { try { Wr ...

  3. JS-4-if

    流程控制结构1 顺序结构 alert(10); alert(20);2 分支结构(选择结构) * IF 2.1  if(条件) { 条件成立时执行的语句 } else { 条件不成立时执行的语句 } ...

  4. js实现农历时间代码

    var dNow = new Date(); var CalendarData=new Array(100); var madd=new Array(12); var tgString="甲 ...

  5. [Linux] Extend space of root disk in Linux7

    [root@node1 ~]# df -hFilesystem Size Used Avail Use% Mounted on/dev/mapper/centos-root 26G 17G 9.8G ...

  6. spring boot hello world

    本文讲解初始用户搭建spring boot 工程. 新建工程目录结构: application.java放在最外层的包目录里 先添加pom.xml的依赖包: <project xmlns=&qu ...

  7. Spring 基础知识(一)基本概念 DI、IOC、AOP

    DI(依赖注入) 和IOC(控制反转)都是一种设计思想,要理解他们,让我们从coding中的一些痛点入手. 依赖注入 Dependency Injection : 如果A类要使用B类的一个方法,首先必 ...

  8. Redis的基本知识

    Redis: 1. 概念:开源的高性能键值对数据库, 提供多种键值对数据类型:字符串.(离散)哈希.列表.集合.有序集合类型 内部储存与持久化:内存的读写速度远高于磁盘:自身提供持久化机制(RDB.A ...

  9. JavaWeb项目三要素

  10. 2—ARM中的异常中断

    ARM体系中的3种控制程序执行的方式 正常执行过程中,每执行1条ARM指令,PC的值加4个字节:每执行1条Thumb指令,PC的值加2个字节.整个过程按照顺序执行. 通过跳转指令,调到特定的地址开始执 ...