前言:
装饰器本质是一个Python函数,它可以让其他函数在不需要作任何
代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象,
它经常用于有切面需求的场景,比如插入日志、性能测试、事物处理、缓
存、权限校验等场景,装饰器是解决这类问题的绝佳设计,有了装饰器,
我们就可以抽离出大量于函数的功能本身无关的雷同代码并继续使用。
正文:
一、装饰器的基础练习
装饰器:
把一个函数当作参数,返回一个替代版的函数,本质就是一个返回函数的
函数,在不改变元函数的基础上增加函数的功能,
1、示例1:
def des(fun):
def add_info():
print('清明节快乐')
fun()
return add_info
@des
def login():
print('hello world')
@des
def logout():
print('hello westos')
login()
logout()
执行结果:
/home/kiosk/PycharmProjects/westos6/venv/bin/python /home/kiosk/PycharmProjects/westos6/装饰器.py
清明节快乐
hello world
清明节快乐
hello westos
Process finished with exit code 0
示例2:函数对修改是封闭的,对扩展是开放的
import time
def sec(fun):
def add_info():
a = time.time()
fun()
b=time.time()
c = b - a
print('时间差为:%.10f' %(c))
return add_info
@sec
def f1():
print(time.time())
print('This is a function')
@sec
def f2():
print(time.time())
print('This is a function2')
f1()
f2()
执行结果:
/home/kiosk/PycharmProjects/westos6/venv/bin/python /home/kiosk/PycharmProjects/westos6/装饰器练习2.py
1554631396.7552593
This is a function
时间差为:0.0000474453
1554631396.7553174
This is a function2
时间差为:0.0000092983
Process finished with exit code 0
示例3、含参数的装饰器
import time
def decoator(fun):
def wropper(*args):
print(time.time())
fun(*args)
return wropper
@decoator
def f1(fun_name):
print('This is a function' + ' ' + fun_name)
@decoator
def f2(fun_name):
print('This is a function' + ' ' + fun_name)
f1('1,2,3,4')
f2('4,5,6,7')
执行结果:
/home/kiosk/PycharmProjects/westos6/venv/bin/python /home/kiosk/PycharmProjects/westos6/含参数的装饰器.py
1554632121.0207565
This is a function 1,2,3,4
1554632121.0207922
This is a function 4,5,6,7
Process finished with exit code 0
示例4、包含多个参数和关键数参数的装饰器
import time
def decortor(fun):
def warrper(*args,**kwargs):
print(time.time())
fun(*args,**kwargs)
return warrper
@decortor
def f1(function_name1,function_name2,**kwargs):
print('This is a function' + '' + function_name1)
print('This a function' + '' + function_name2)
print(kwargs)
f1('test','test2',a=2,b=3,c=5)
执行结果:
/home/kiosk/PycharmProjects/westos6/venv/bin/python /home/kiosk/PycharmProjects/westos6/含关键字的装饰器.py
1554633214.0698268
This is a functiontest
This a functiontest2
{'a': 2, 'b': 3, 'c': 5}
Process finished with exit code 0
示例5、
import time
def add_log (fun):
def wropperr(*args,**kwargs):
start= time.time()
res = fun(*args,**kwargs)
endtime = time.time()
print('运行时间为:%.6f,函数返回值为:%d' %((endtime-start),res))
return wropperr
@add_log
def add(x,y):
return x + y
add(2,2)
执行结果:
/home/kiosk/PycharmProjects/westos6/venv/bin/python /home/kiosk/PycharmProjects/westos6/装饰器5.py
运行时间为:0.000008,函数返回值为:4
Process finished with exit code 0
示例6、进行多个装饰器的练习
注意的是:当函数遇到多个装饰器时,执行顺序为,要添加函数外面的
代码执行顺序为从下到上,添加函数内部执行顺序为从下到上。
def dectors_a(fun):
print('Get in decotor_a')
def inner_a(*args,**kwargs):
print('Ger in inner_a')
res = fun(*args,**kwargs)
return res
return inner_a
def dector_b(fun):
print('Get in dector_b')
def inner_b(*args,**kwargs):
print('Get in inner_b')
res = fun(*args,**kwargs)
return res
return inner_b
@dector_b
@dectors_a
def add(x,y):
return x + y
add(1,3)
执行结果:
/home/kiosk/PycharmProjects/westos6/venv/bin/python /home/kiosk/PycharmProjects/westos6/多个装饰器的练习.py
Get in decotor_a
Get in dector_b
Get in inner_b
Ger in inner_a
Process finished with exit code 0
二、进行装饰器的练习:
1、需求:
:问题1:被装饰的函数有返回值
:问题2:如何保留被装饰函数的函数名和帮助信息文档
import time
import random
import string
import functools
li = [random.choice(string.ascii_letters) for i in range(100)]
print(li)
def Tinner(fun):
def wropper(*args,**kwargs):
start = time.time()
res = fun(*args,**kwargs)
endtime = time.time()
print('运行时间为:.%.6f' %(endtime-start))
return res
return wropper
@Tinner
def com_add():
s= ''
for i in li:
s += (i + ',')
print(s)
@Tinner
def join_add():
print(''.join(li))
@Tinner
def fun_list(n):
return [i * 2 for i in range(n)]
print(fun_list(10))
join_add()
print(fun_list.__doc__)
print(fun_list.__name__) ###装饰器中添加函数的名称
print(time.ctime()) ###装饰器中调用的时间
执行结果:
/home/kiosk/PycharmProjects/westos6/venv/bin/python /home/kiosk/PycharmProjects/westos6/装饰器的练习1.py
['p', 'z', 'l', 'o', 'H', 'T', 'V', 'X', 'u', 'F', 'x', 'j', 'X', 'g', 't', 'U', 'S', 'i', 'j', 'a', 'I', 'k', 'i', 'v', 'f', 'v', 'Z', 'R', 'B', 'E', 'v', 'M', 'L', 'E', 'B', 'r', 'L', 'g', 'B', 'B', 'K', 'O', 'O', 'u', 'E', 'b', 'j', 'g', 'r', 'b', 'x', 'R', 'x', 'n', 'n', 'k', 'I', 'K', 'y', 'I', 'B', 'D', 'Q', 'C', 'K', 'x', 'x', 'L', 'X', 'Q', 'G', 'L', 'O', 'd', 'g', 'y', 'C', 'x', 'A', 'M', 'A', 'b', 'P', 'a', 'X', 'B', 'i', 's', 'F', 'u', 'g', 'h', 'M', 'w', 'l', 'C', 'L', 'c', 'Q', 'k']
运行时间为:.0.000003
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
pzloHTVXuFxjXgtUSijaIkivfvZRBEvMLEBrLgBBKOOuEbjgrbxRxnnkIKyIBDQCKxxLXQGLOdgyCxAMAbPaXBisFughMwlCLcQk
运行时间为:.0.000005
None
wropper
Mon Apr 8 00:12:46 2019
Process finished with exit code 0
练习2、
import functools
import inspect
def is_admin(fun):
@functools.wraps(fun)
def weapper(*args,**kwargs):
#inspect.gercallargs返回是一个字典,key值是形参,value值是对应的实参
inspect_res = inspect.getcallargs(fun,*args,**kwargs)
print('insepect的返回值为:%s'%(inspect_res))
if inspect_res.get('name') == 'root':
res = fun(*args,**kwargs)
return res
else:
print('not root user!')
return weapper
@is_admin
def add_user(name):
print('添加用户信息')
@is_admin
def del_user(name):
print('删除用户信息')
add_user('root')
del_user('root')
执行结果:
/home/kiosk/PycharmProjects/westos6/venv/bin/python /home/kiosk/PycharmProjects/westos6/imspect中的装饰器.py
insepect的返回值为:{'name': 'root'}
添加用户信息
insepect的返回值为:{'name': 'root'}
删除用户信息
Process finished with exit code 0
练习3、
""" 编写装饰器required_types, 条件如下: 1). 当装饰器为@required_types(int,float)确保函数接收到的 每一个参数都是int或者float类型; 2). 当装饰器为@required_types(list)确保函数接收到的每一个参数都是list类型; 3). 当装饰器为@required_types(str,int)确保函数接收到的每 一个参数都是str或者int类型; 4). 如果参数不满足条件, 打印 TypeError:参数必须为xxxx类 型 """
"""
编写装饰器required_types, 条件如下:
1). 当装饰器为@required_types(int,float)确保函数接收到的
每一个参数都是int或者float类型;
2). 当装饰器为@required_types(list)确保函数接收到的每一个参数都是list类型;
3). 当装饰器为@required_types(str,int)确保函数接收到的每
一个参数都是str或者int类型;
4). 如果参数不满足条件, 打印 TypeError:参数必须为xxxx类
型
"""
import functools
def required_type(*kinds):
def required_int(fun):
@functools.wraps(fun)
def wropper(*args,**kwargs):
for i in args:
if not isinstance(i,kinds):
raise TypeError('参数必须为%s,%a'% kinds)
else:
res = fun(*args,**kwargs)
return res
return wropper
return required_int
def add(a,b):
return a + b
print(add('s','s'))
执行结果:
/home/kiosk/PycharmProjects/westos6/venv/bin/python /home/kiosk/PycharmProjects/westos6/装饰器的练习3.py
ss
Process finished with exit code 0
三、Python 中的第三方模块
示例1:第三方模块指的是别人写好的一些模块,可以实现一定的功能
实现给微信发送指定的内容
import random
import time
import itchat
itchat.auto_login()
while True:
itchat.send('welcome use weixin',toUserName='filehelper')
itchat.send_file('/etc/passwd',toUserName='filehelper')
time.sleep(random.randint(1,3))
执行结果:
/home/kiosk/PycharmProjects/westos7/venv/bin/python /home/kiosk/PycharmProjects/westos7/第三方模快.py
Getting uuid of QR code.
Downloading QR code.
Please scan the QR code to log in.
Please press confirm on your phone.
Loading the contact, this may take a little while.
Login successfully as 左手边
2、使用第三方模块实现统计微信中的好友
import random
import time
import itchat
itchat.auto_login()
friends = itchat.get_friends()
info = {}
for friend in friends[1:]:
if friend['Sex'] == 1:
info['male'] = info.get('male',0) + 1
elif friend['Sex'] == 2:
info['female'] = info.get('female',0) + 1
else:
info['other'] = info.get('other',0) + 1
print(info)
执行结果:
/home/kiosk/PycharmProjects/westos7/venv/bin/python /home/kiosk/PycharmProjects/westos7/第三方模快.py
Getting uuid of QR code.
Downloading QR code.
Please scan the QR code to log in.
Please press confirm on your phone.
Loading the contact, this may take a little while.
Login successfully as 左手边
{'male': 57, 'other': 11, 'female': 39}
Process finished with exit code 0