11 装饰器

装饰器介绍与简单实现

1. 什么是装饰器
器:指的是具备某一功能的工具
装饰:指的是为被装饰器对象添加新功能

装饰器就是用来为被装饰器对象添加新功能的工具
注意:装饰器本身可以是任意可调用对象,被装饰器的对象也可以是任意可调用对象


2. 为何要用装饰器
开放封闭原则:封闭指的是对修改封闭,对扩展开放

装饰器的实现必须遵循两大原则:
1. 不修改被装饰对象的源代码
2. 不修改被装饰器对象的调用方式

装饰器的目标:就是在遵循1和2原则的前提下为被装饰对象添加上新功能

3. 怎么用装饰器
'''
import time

def index():
print('welcome to index page')
time.sleep(3)

def outter(func): # func=最原始那个index的内存地址
def wrapper():
start=time.time()
func() #最原始的那个index的内存地址()
stop=time.time()
print('run time is %s' %(stop - start))
return wrapper

index=outter(index) #index=outter(最原始那个index的内存地址) #index=wrapper的内存地址
index() #wrapper的内存地址()



深入学习
import time

def index():
print('welcome to index page')
time.sleep(3)

def home(name):
print('welcome %s to home page' %name)
time.sleep(2)
return 123

def timmer(func): #func=最原始那个home函数的内地址
def wrapper(*args,**kwargs): #args=('egon',) kwargs={}
start=time.time()
res=func(*args,**kwargs) #最原始那个home函数的内地址('egon')
stop=time.time()
print('run time is %s' %(stop - start))
return res
return wrapper

# index=timmer(index)
index()

home=timmer(home) #home=outter(最原始那个home函数的内地址) #home=wrapper函数的内地址

res=home('egon') # res=wrapper函数的内地址('egon')
print(res)
装饰器的语法糖
# 装饰器的语法糖:在被装饰对象正上方单独一行写@装饰器的名字
# 运行原理:
# python解释器一旦运行到@装饰器的名字,就会调用装饰器,然后将被装饰函数的内存地址当作参数
#传给装饰器,最后将装饰器调用的结果赋值给原函数名

# import time
#
# def timmer(func): #func=最原始那个home函数的内地址
# def wrapper(*args,**kwargs): #args=('egon',) kwargs={}
# start=time.time()
# res=func(*args,**kwargs) #最原始那个home函数的内地址('egon')
# stop=time.time()
# print('run time is %s' %(stop - start))
# return res
# return wrapper
#
# @timmer #index=timmer(index)
# def index():
# print('welcome to index page')
# time.sleep(3)
#
# @timmer #home=timmer(home)
# def home(name):
# print('welcome %s to home page' %name)
# time.sleep(2)
# return 123
#
# index()
# res=home('egon') # res=wrapper函数的内地址('egon')
# print(res)
#
#



import time

# 装饰器模板
def outter(func):
def wrapper(*args,**kwargs):
#在调用函数前加功能
res=func(*args,**kwargs) #调用被装饰的\也就是最原始的那个函数
#在调用函数后加功能
return res
return wrapper

@outter #index=outter(index) #index=wrapper
def index():
print('welcome to index page')
time.sleep(3)

index()


叠加多个装饰器

'''
import time

def timmer(func): #func=wrapper2
def wrapper1(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs) #res=wrapper2(*args,**kwargs)
stop=time.time()
print('run time is %s' %(stop - start))
return res
return wrapper1

def auth(func): #func=最原始的那个index的内存地址
def wrapper2(*args,**kwargs):
inp_user = input('please input your username: ').strip()
inp_pwd = input('please input your password: ').strip()
if inp_user == 'egon' and inp_pwd == '123':
print('login successfull')
res=func(*args,**kwargs) # 调用最原始的那个/也就是被装饰的那个函数
return res
else:
print('username or password error')
return wrapper2

# 解释@语法的时候是自下而上运行
# 而执行装饰器内的那个wrapper函数时的是自上而下
@timmer # index=timmer(wrapper2) #index=wrapper1
@auth # index=auth(最原始的那个index的内存地址) #index=wrapper2
def index():
print('welcome to index page')
time.sleep(3)

index() #wrapper1()

'''



# import time
#
# def timmer(func):
# print('timmer')
# def wrapper1(*args,**kwargs):
# start=time.time()
# res=func(*args,**kwargs) #res=wrapper2(*args,**kwargs)
# stop=time.time()
# print('run time is %s' %(stop - start))
# return res
# return wrapper1
#
# def auth(func):
# print('auth')
# def wrapper2(*args,**kwargs):
# inp_user = input('please input your username: ').strip()
# inp_pwd = input('please input your password: ').strip()
# if inp_user == 'egon' and inp_pwd == '123':
# print('login successfull')
# res=func(*args,**kwargs) # 调用最原始的那个/也就是被装饰的那个函数
# return res
# else:
# print('username or password error')
# return wrapper2
#
#
# @auth # index=auth(wrapper1) #index=wrapper2
# @timmer #timmer(最原始的index)返回wrapper1
# def index():
# print('welcome to index page')
# time.sleep(3)
#
# index() #wrapper2()
#




import time



def outter1(func1): #func1=wrapper2
print('outter1')
def wrapper1(*args,**kwargs):
print('wrapper1')
res1=func1(*args,**kwargs) #res1=wrapper2(*args,**kwargs)
return res1
return wrapper1

def outter2(func2): #func2=最原始的那个index的内存地址
print('outter2')
def wrapper2(*args,**kwargs):
print('wrapper2')
res2=func2(*args,**kwargs)
return res2
return wrapper2


@outter1 # index=outter1(wrapper2) #index=wrapper1
@outter2 #outter2(最原始的那个index的内存地址) ===> wrapper2
def index():
print('welcome to index page')
time.sleep(3)

index() #wrapper1()

'''
outter2
outter1
wrapper1
wrapper2

'''

有参装饰器
import time

current_user={'username':None}

# 补充:所有的数据类型的值自带布尔值,可以直接当作条件去用,只需要记住布尔值为假的那一些值即可(0,空,None)


def login(engine='file'): #engine='mysql'
def auth(func): #func=最原始那个index的内存地址
def wrapper(*args,**kwargs):
if current_user['username']:
print('已经登录过了,无需再次登陆')
res=func(*args,**kwargs)
return res

if engine == 'file':
inp_user = input('please input your username: ').strip()
inp_pwd = input('please input your password: ').strip()
if inp_user == 'egon' and inp_pwd == '123':
print('login successfull')
current_user['username']=inp_user # 在登陆成功之后立刻记录登录状态
res=func(*args,**kwargs) # res=最原始那个index的内存地址(*args,**kwargs)
return res
else:
print('username or password error')
elif engine == 'mysql':
print('基于mysql的认证机制')
elif engine == 'ldap':
print('基于ldap的认证机制')
else:
print('无法识别的认证源')
return wrapper
return auth

@login('file') #@auth # index=auth(最原始那个index的内存地址) #index=wrapper
def index():
print('welcome to index page')
time.sleep(3)

@login('file')
def home(name):
print('welcome %s to home page' %name)
time.sleep(2)
return 123


index() #wrapper()
res=home('egon')
print(res)



# 有参装饰器的模板
def outter1(x,y,z):
def outter2(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
return outter2

# 无参装饰器的模板
def outter(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper

转载于:https://www.cnblogs.com/ouyang99-/p/10414876.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/463405.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言 ,嵌入式 ,数据结构 面试题目(3)

182 链表题:一个链表的结点结构 struct Node { int data ; Node *next ; }; typedef struct Node Node ; (1)已知链表的头结点head,写一个函数把这个链表逆序 ( Intel)Node * ReverseList(Node *head) //链表逆序 { if ( head NULL || head->next NULL ) retur…

C++11 新特性 —— 关键字noexcept

转载;https://www.cnblogs.com/sword03/p/10020344.html 1 关键字noexcept 从C11开始,我们能看到很多代码当中都有关键字noexcept。比如下面就是std::initializer_list的默认构造函数,其中使用了noexcept。 constexpr initializer_list() noexcept: _M…

统一项目管理平台(UMPlatForm.NET)-4.7 组织机构管理模块

统一项目管理平台(UMPlatForm.NET) 4.7 组织机构管理模块 统一项目管理平台(UMPlatForm.NET),基于.NET的快速开发、整合框架。 4.7 组织机构管理模块 组织机构管理模块提供直观方便的组织机构管理,以树型结构显示单位和…

开源GIS系统关系图

转载于:https://www.cnblogs.com/penglink/archive/2009/06/26/1511373.html

c++常用知识点,易错点,面试常问点

1.谈谈你对C内存分配的理解1.1 还是的先看看C对内存分为哪几个区?1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。想知道为什么效率高吗?因为…

g++编译时的常用选项说明

最近在做一个新的项目,所有的代码都是新写的没有参考的部分,因此遇到了一些问题,主要是在编译方面的问题,算是对这2周时间的总结: g编译时使用了 -O3级别,参数如下: (1)、-g -O3 -DNDEBUG -fn…

详解mybatis映射配置文件

一 mybatis 映射文件结构 mybatis映射配置文件存在如下顶级元素,且这些元素按照如下顺序被定义。 cache – 给定命名空间的缓存配置。cache-ref – 其他命名空间缓存配置的引用。 resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中…

利用ACS来实现AAA服务

ACS简介思科安全访问控制服务器(Cisco Secure Access Control Sever)是一个高度可扩展、高性能的访问控制服务器,提供了全面的身份识别网络解决方案,是思科基于身份的网络服务(IBNS)架构的重要组件。Cisco Secure ACS通过在一个集…

Nginx常用命令有哪些?

最近在集群数据库之前部署了Ngnix来实现负载均衡和解决高并发情况下服务器压力过重的问题。 常用的命令有如下: nginx -t : 验证配置文件 nginx -s stop : 快速停止(不管有没有正在处理的请求,强制退出) nginx -s quit : 正常停止(处理完已经接收的请…

C/C++二维数组名和二级指针的联系与区别

1. 指针 1.1 一个指针包含两方面:a) 地址值;b) 所指向的数据类型。 1.2 解引用操作符(dereference operator)会根据指针当前的地址值,以及所指向的数据类型,访问一块连续的内存空间(大小由指针所…

BN层

论文名字:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift 论文地址:https://arxiv.org/abs/1502.03167 BN被广泛应用于深度学习的各个地方,由于在实习过程中需要修改网络,修改的…

POJ 3613

1 //共T条路&#xff0c;求从S到E经过N条路径的最短路径 2 #include <iostream>3 #include <fstream>4 #include <string.h>5 #include <algorithm>6 using namespace std;7 8 #define CIR(n, m) for (int i0; i<n; i) for (int j0; j<m; j)9 co…

C语言中字符型和字符串型的对比

C语言中字符型和字符串型的对比字符型&#xff1a;C语言中字符用单引号括起来&#xff0c;存储方式以ASCII编码二进制形式存储&#xff0c;占用一个字节如&#xff1a;a,b,c,A等注意&#xff1a;在C语言中将字符型看成特别短的整形&#xff0c;unsigned int 的长度刚好是0-256的…

深入浅出 Javascript API(二)--地图显示与基本操作 转

深入浅出 Javascript API&#xff08;二&#xff09;--地图显示与基本操作 地图显示与基本操作&#xff08;放大、缩小、移动、坐标显示&#xff09;是JavascriptAPI的基本功能&#xff0c;也是一个WebGIS应用的基本内容&#xff0c;Javascript提供了非常便捷的开发方法&#x…

「PKUSC2018」神仙的游戏 - 题解

「PKUSC2018」神仙的游戏 题意&#xff1a;给出一个01?串&#xff0c;其中?可以代替成为0或1&#xff0c;令 $ F(i) $ 表示是否存在长度为 $ i $ 的border&#xff0c;求 $ (F(1) \times 1 \times 1) \bigoplus (F(2) \times 2 \times 2) \bigoplus (F(3) \times 3 \times 3)…

常用哈希函数的比较及其实现

基本概念 所谓完美哈希函数。就是指没有冲突的哈希函数。即对随意的 key1 ! key2 有h(key1) ! h(key2)。 设定义域为X&#xff0c;值域为Y, n|X|,m|Y|。那么肯定有m>n,假设对于不同的key1,key2属于X,有h(key1)!h(key2)&#xff0c;那么称h为完美哈希函数&#xff0c;当mn时&…

C语言 ,嵌入式 ,c++,数据结构 面试题目(4)

sizeof是C/C中的一个操作符&#xff08;operator&#xff09;&#xff0c;简单的说其作用就是返回一个对象或者类型所占的内存字节数。与strlen的区别&#xff1a;一、sizeof是运算符&#xff0c;确切的说是一个编译时运算符&#xff0c;参数可以是数组、指针、类型、对象、函数…

把链接伪装成按钮

<input type"button" οnclick"location.hrefhttp://www.lemongtree.net/;" value"GO">转载于:https://www.cnblogs.com/xiaoman_890/archive/2009/07/07/1518471.html

c语言中char *name 与char name 的区别

要点&#xff1a;char* name"abc"指的是常量字符串&#xff0c;不可以修改指针&#xff0c;是兼容老的写法&#xff1b;char[] name"abc"是指针&#xff0c;可以修改&#xff1b; 在学习过程中发现了一个以前一直默认的错误&#xff0c;同样char *c "…

Spring事务配置的五种方式

Spring事务配置的五种方式前段时间对Spring的事务配置做了比较深入的研究&#xff0c;在此之间对Spring的事务配置虽说也配置过&#xff0c;但是一直没有一个清楚的认识。通过这次的学习发觉Spring的事务配置只要把思路理清&#xff0c;还是比较好掌握的。总结如下&#xff1a;…