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

  这是一个装饰器的步骤图

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. Cognos无法解密来着内容库的用户名和密码凭证

    1. 问题描述 启动Cognos失败,报错代码为QE-DEF-0368. 2. 问题分析 Frame Work和Cognos Server安装在不同的目录和/或不同的机器上. 3. 解决方案 需要把S ...

  2. 利用pom配置实现静态文件拷贝

    java项目有时候需要将一些静态文件拷贝到生成的test-class文件夹或者其他地方,虽然手动拷贝可以做到,但是很麻烦.今天主要讲解如何利用pom.xml进行动态的拷贝. 具体的配置信息如下,在de ...

  3. mysql 执行sql流程

    客户端发送sql 语句后的堆栈 #0 0x0000000100370565 in do_command(THD*) at percona-server-Percona-Server-5.6.37-82 ...

  4. roadhog 构建优化

    背景 一个 antd 项目打包时间太长,竟然快二十分钟了,有时还会导致内存溢出,查了一些资料(thanks funfish),解决方法如下 roadhog.js问题 roadhog.js 是类似可配置 ...

  5. python小总结2(time,os)

    一.时间模块 1.1 Time time.time():获取时间戳,结果为一个浮点数 time.gtime():获取时间的元组形式 time.localtime():获取的是当地时间 time.mkt ...

  6. Android使用Jenkins自动化构建测试打包apk

    Jenkins这东西搭建起来真是一点也不省心啊,看着别人的教程摸着石头过河,配置的东西有点多啊,稍有不慎,就构建不成功啦!即使步骤跟别人一样也会报各种乱七八糟的错误啊哈哈~~这东西只能佛系搭建~~在经 ...

  7. PHP运算符知识

    1.三目运算符: $a =1; echo $a>0 ? '大于0':$a==0 ? '等于0':'小于0'; 貌似应该输出:大于0 其实: 然而,上面语句的实际输出是't',因为三元运算符是从左 ...

  8. Android : Camera之CHI API

    一.CAM CHI API功能介绍: CHI API建立在Google HAL3的灵活性基础之上,目的是将Camera2/HAL3接口分离出来用于使用相机功能,它是一个灵活的图像处理驱动程序(摄像头硬 ...

  9. JDBC连接ORACLE的三种URL格式

    格式一: Oracle JDBC Thin using an SID jdbc:oracle:thin:@host:port:SID 例如: jdbc:oracle:thin:@localhost:1 ...

  10. 2018-2019-2 20175224 实验一《Java开发环境的熟悉》实验报告

    实验报告封面 实验内容与步骤 Java开发环境的熟悉-1 1.建立“自己学号exp1”的目录 2.在“自己学号exp1”目录下建立src,bin等目录 3.javac.java的执行在“自己学号exp ...