装饰器的原则

1)不修改被修饰函数的源代码;

2)不修改被修饰函数的调用方式;

装饰器的知识点 = 高阶函数 + 函数嵌套 + 闭包

1. 只用高阶函数写装饰器--->有瑕疵

import time

def foo():
print('this is foo')
# return foo def timer(func):
starttime = time.time()
func()
stoptime = time.time()
print('使用的时间是:%s' %(stoptime - starttime))
return func foo = timer(foo)
foo() #执行结果是:
# this is foo
# 使用的时间是:0.00013685226440429688
# this is foo #多了一次执行结果

2. 闭包其实就是函数的嵌套

def First(name):
print('FirstLayer:%s' %name)
def Second():
name = 'bbb'
print('SecondLayer:%s' %name)
def Third():
name = 'ccc'
print('ThirdLayer:%s' %name)
Third()
Second()
First('aaa')

3. 函数闭包装饰器基本实现

# 实现阶段1:只需要在原来函数调用之前进行赋值操作。
import time def timer(func): #func == test
def good():
starttime = time.time()
func()
stoptime = time.time()
print('程序消耗的时间是:%s' %(stoptime - starttime))
return good def test():
print('这是test函数') test = timer(test) #此处函数运行的结果是return的good,可以看下一步证实。
print(timer(test)) #<function timer.<locals>.good at 0x10e3cb700>,因此需要下一步运行返回值函数good。
test() #test = good
# 实现阶段2:通过语法糖改进后,完全不需要动原来函数;
import time def timer(func): #func == test
def good():
starttime = time.time()
func()
stoptime = time.time()
print('程序消耗的时间是:%s' %(stoptime - starttime))
return good @timer #@timer 相当于 test = timer(test) def test():
print('这是test函数')
test()
# 实现阶段3:如何打印出真正test的返回值
import time def timer(func): #func == test
def good():
starttime = time.time()
res = func() #就是在运行test()
stoptime = time.time()
print('程序消耗的时间是:%s' %(stoptime - starttime))
return res
return good @timer #@timer 相当于 test = timer(test) def test():
print('这是test函数')
return '这是test的返回值'
ras = test()
print(ras)
# 阶段4装饰器适用于不同参数个数的函数
import time def timer(func): #func == test
def good(*args,**kwargs):
starttime = time.time()
res = func(*args,**kwargs) #就是在运行test()
stoptime = time.time()
print('程序消耗的时间是:%s' %(stoptime - starttime))
return res
return good @timer #@timer 相当于 test = timer(test) def test(name,age,gender):
print('这是test函数,名字是%s,年龄是%s,性别是%s' %(name,age,gender))
return '这是test的返回值'
ras = test('aaa','','male')
print(ras) @timer #@timer 相当于 test1 = timer(test1)
def test1(name,age,gender,hight):
print('这是test1函数,,名字是%s,年龄是%s,性别是%s,身高是%s' %(name,age,gender,hight))
return '这是test1的返回值'
ras = test1('bbb','','male','')
print(ras) # 如下为返回结果:
# 这是test函数,名字是aaa,年龄是18,性别是male
# 程序消耗的时间是:8.0108642578125e-05
# 这是test的返回值
# 这是test1函数,,名字是bbb,年龄是20,性别是male,身高是175
# 程序消耗的时间是:1.0013580322265625e-05
# 这是test1的返回值

4. 解压序列补充

# 使用解压序列取列表中的最开头和最结尾的值,可灵活使用。
>>> l = [1,2,3,4,5,6]
>>> a,*_,b = l
>>> l
[1, 2, 3, 4, 5, 6]
>>> a
1
>>> b
6
>>> a,*b,c = l
>>> a
1
>>> b
[2, 3, 4, 5]
>>> c
6
#快速交换两个变量的值
>>> f1,f2 = 1,2
>>> f1
1
>>> f2
2
>>> f1,f2 = f2,f1
>>> f1
2
>>> f2
1

5. 终极版装饰器-带参数验证功能的装饰器

user_list=[
{'name':'alex','passwd':''},
{'name':'linhaifeng','passwd':''},
{'name':'wupeiqi','passwd':''},
{'name':'yuanhao','passwd':''},
]
current_dic={'username':None,'login':False} def auth(auth_type='filedb'):
def auth_func(func):
def wrapper(*args,**kwargs):
print('认证类型是',auth_type)
if auth_type == 'filedb':
if current_dic['username'] and current_dic['login']:
res = func(*args, **kwargs)
return res
username=input('用户名:').strip()
passwd=input('密码:').strip()
for user_dic in user_list:
if username == user_dic['name'] and passwd == user_dic['passwd']:
current_dic['username']=username
current_dic['login']=True
res = func(*args, **kwargs)
return res
else:
print('用户名或者密码错误')
elif auth_type == 'ldap':
print('鬼才特么会玩')
res = func(*args, **kwargs)
return res
else:
print('鬼才知道你用的什么认证方式')
res = func(*args, **kwargs)
return res return wrapper
return auth_func @auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type --->index=auth_func(index)
def index():
print('欢迎来到京东主页') @auth(auth_type='ldap')
def home(name):
print('欢迎回家%s' %name)
#
@auth(auth_type='sssssss')
def shopping_car(name):
print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃')) # print('before-->',current_dic)
# index()
# print('after--->',current_dic)
# home('产品经理')
shopping_car('产品经理')

Python函数装饰器的更多相关文章

  1. Python函数装饰器原理与用法详解《摘》

    本文实例讲述了Python函数装饰器原理与用法.分享给大家供大家参考,具体如下: 装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值 ...

  2. python函数-装饰器

    python函数-装饰器 1.装饰器的原则--开放封闭原则 开放:对于添加新功能是开放的 封闭:对于修改原功能是封闭的 2.装饰器的作用 在不更改原函数调用方式的前提下对原函数添加新功能 3.装饰器的 ...

  3. Python函数装饰器高级用法

    在了解了Python函数装饰器基础知识和闭包之后,开始正式学习函数装饰器. 典型的函数装饰器 以下示例定义了一个装饰器,输出函数的运行时间: 函数装饰器和闭包紧密结合,入参func代表被装饰函数,通过 ...

  4. Python 函数装饰器

    首次接触到装饰器的概念,太菜啦! Python 装饰器可以大大节省代码的编写量,提升代码的重复使用率.函数装饰器其本质也是一个函数,我们可以把它理解为函数中定义了一个子函数. 例如我们有这么一个需求, ...

  5. Python @函数装饰器及用法

    1.函数装饰器的工作原理 函数装饰器的工作原理是怎样的呢?假设用 funA() 函数装饰器去装饰 funB() 函数,如下所示: #funA 作为装饰器函数 def funA(fn): #... fn ...

  6. Python @函数装饰器及用法(超级详细)

    函数装饰器的工作原理是怎样的呢?假设用 funA() 函数装饰器去装饰 funB() 函数,如下所示: #funA 作为装饰器函数 def funA(fn): #... fn() # 执行传入的fn参 ...

  7. Python高手之路【四】python函数装饰器

    def outer(func): def inner(): print('hello') print('hello') print('hello') r = func() print('end') p ...

  8. python 函数 装饰器 内置函数

    函数 装饰器 内置函数 一.命名空间和作用域 二.装饰器 1.无参数 2.函数有参数 3.函数动态参数 4.装饰器参数 三.内置函数 salaries={ 'egon':3000, 'alex':10 ...

  9. Python 函数装饰器简明教程

    定义类的静态方法时,就使用了装饰器.其实面向对象中的静态方法都是使用了装饰器. @staticmethod def jump(): print(" 3 meters high") ...

  10. Python高手之路【四】python函数装饰器,迭代器

    def outer(func): def inner(): print('hello') print('hello') print('hello') r = func() print('end') p ...

随机推荐

  1. lwip eth插拔网线自动维护接口状态

    硬件连线就是将dp83848的INT脚连到STM32的某个中断脚上,这里是PB14 PB14的中断处理函数中,会释放一个信号量,这里只是发生链路状态改变中断(网线插上或拔下) void EXTI15_ ...

  2. zabbix-proxy配置文件参数说明

    配置文件路径: /etc/zabbix/zabbix_proxy.conf Server=10.0.0.10 #<===指定zabbix server的ip地址或主机名 Hostname=zab ...

  3. Vue.js 计算属性computed和methods的区别

    在vue.js中,有methods和computed两种方式来动态当作方法来用的 如下: 两种方式在这种情况下的结果是一样的 写法上的区别是computed计算属性的方式在用属性时不用加(),而met ...

  4. 标准 I/O 和管道

    1.标准输入和输出1>程序:指令+数据(指令服务于数据) 读入数据:input 输出数据:output 2>三种 I/O 设备 Linux 给程序提供三种 I/O 设备 标准输入(STDI ...

  5. Python学习小记(1)---import小记

    在这种目录结构下,import fibo会实际导入fibo文件夹这个module λ tree /F 卷 Programs 的文件夹 PATH 列表 卷序列号为 BC56-3256 D:. │ fib ...

  6. redis 5.0.7 源码阅读——跳跃表skiplist

    redis中并没有专门给跳跃表两个文件.在5.0.7的版本中,结构体的声明与定义.接口的声明在server.h中,接口的定义在t_zset.c中,所有开头为zsl的函数. 一.数据结构 单个节点: t ...

  7. mysql实现远程登录

    CentOS7上安装mysql后,想要实现mysql远程登录. 主要解决二个问题:(1)为mysql用户授予远程登录权限(改表法或授权法):(2)防火墙开放3306端口. (一)授予登录权限 mysq ...

  8. Linux 网络客户端工具

    ping命令 发送ICMP协议的echo request给目标主机 常用选项: 从指定的本机接口发送ICMP:-I INTERFACE 本机有多个接口(网卡),可以选择从哪个接口发:-I(大写i) 接 ...

  9. MFC/QT 学习笔记(一)——认识windows基础库

    MFC (微软基础类库),Windows系统平台做GUI尚且OK,但不支持跨平台. //Windows消息机制: //1.SDK与API Software Development Kit,为特定软件框 ...

  10. 关于elementui的table组件单元格的内容自定义写法

    ------------恢复内容开始------------ 记录老哥的写法 columns是表格的配置文件 在表格渲染的时候通过renderTableCell传入表格的row以及配置文件中的rend ...