装饰器的概念:
装饰器的实现是函数里面嵌套函数
装饰器的本质是一个函数,他可以让其他函数在不需要做任何代码改动的前提下增加额外的功能;
装饰器需要传递一个函数,返回值也是一个函数对象。
装饰器需求:
获取每个函数的执行时间
函数执行之后计算时间
import time
import random
import string
print string.ascii_letters
li=[random.choice(string.ascii_letters)for i in range(10)]
def timeit(fun):
def wrapper(*args,**kwargs):#接受可变参数和关键字参数 args:元组kwargs:字典
#函数执行之前
start_time=time.time()
#执行函数
fun(*args,**kwargs)
#函数执行之后
end_time=time.time()
print'运行时间:%.6f'%(end_time-start_time)
return wrapper
@timeit
def con_add():
s=''
for i in li:
s+=(i+',')
print s
@timeit
def join_add():
print ','.join(li)
@timeit
def fun_list(n):
print [2*i for i in range(n)]
@timeit
def fun_map(n):
print list(map(lambda x : x*2,range(n)))
con_add()
join_add()
fun_list(4000)
fun_map(4000)
map和匿名函数
def f(x):
return x*x
#map()传入的第一个参数是一个函数,第二个参数是一个序列
print map(f,[1,2,3,4])
print map(lambda x:x*x,[1,2,3,4])
问题一:被装饰的函数有返回值的时候怎么办?
问题二:如何保留被装饰函数的函数名和帮助文档信息
import time
import random
import string
import functools
print string.ascii_letters
li=[random.choice(string.ascii_letters)for i in range(10)]
def timeit(fun):
"""这是一个装饰器"""
@functools.wraps(fun)
def wrapper(*args,**kwargs):
"""这是一个wrapper函数"""
start_time=time.time()
res=fun(*args,**kwargs)
end_time=time.time()
print'运行时间:%.6f'%(end_time-start_time)
return res
return wrapper
@timeit
def con_add():
s=''
for i in li:
s+=(i+',')
print s
@timeit
def join_add():
print ','.join(li)
@timeit
def fun_list(n):
"""这是fun_list函数,被timeit装饰"""
return [2*i for i in range(n)]
@timeit
def fun_map(n):
"""这是fun_map函数"""
return list(map(lambda x : x*2,range(n)))
con_add()
join_add()
print fun_list(4000)
print fun_map(4000)
print fun_list.__name__
print fun_list.__doc__
print fun_map.__name__
print fun_map.__doc__
#创建装饰器,要求如下:
1,创建add_log装饰器,被装饰的函数打印日志信息;
2,日志格式为:[字符串时间] 函数名:xxx,运行时间:xxx,运行返回值结果:xxx
import time
print time.ctime()
import functools
def add_log(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
start_time=time.time()
res=fun(*args,**kwargs)
end_time=time.time()
print '[%s]函数名:%s,运行时间:%.5f,运行结果返回值:%d'%(time.ctime(),fun.__name__,end_time-start_time,res)
return res
return wrapper
@add_log
def add(x,y):
time.sleep(1)
return x+y
print add(1,2)
##用户登陆验证的装饰器 is_login
1.如果用户登陆成功,则执行被装饰的函数
2.如果用户登陆不成功,则执行登陆函数
import functools
login_users=['admin','root']
def is_login(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
if kwargs.get('name')in login_users:
res=fun(*args,**kwargs)
return res
else:
res=login()
return res
return wrapper
def login():
return '登陆。。。'
@is_login
def writeblog(name):
return'编写博客'
print writeblog(name='admin')
###编写装饰器,条件如下:
1) 确保函数接收到的每一个参数都是整数
2)如果参数不是整形数,打印错误:参数必须是整数
import functools
def required_ints(fun):
@functools.wraps(fun)
def hanshu(*args,**kwargs):
for i in args:
if isinstance(i,int):
pass
else:
print 'TypeError:参数必须是整形'
break
#if not isinstance(i,int):
#print 'TyperError:必须为整形'
#break
else:
res=fun(*args,**kwargs)
return res
return hanshu
@required_ints
def add(a,b):
return a+b
@required_ints
def mymax(a,b,c,d):
return max(a,b,c,d)
print add(1,2)
print mymax(1,2,3,4)
#多个装饰器的顺序
def decorator_a(func):
print 'Get in decoraor_a'
def inner_a(*args,**kwargs):
print 'Get in inner_a'
res=func(*args,**kwargs)
return res
return inner_a
def decorator_b(func):
print 'Get in decoraor_b'
def inner_b(*args,**kwargs):
print 'Get in inner_b'
res=func(*args,**kwargs)
return res
return inner_b
@decorator_b
@decorator_a
def f(x):
print 'Get in f'
return x*2
print f(1)
####多个函数装饰器的应用
在我们实际的应用场景中,会采用多个装饰器先验证是否登陆成功在验证权限
import functools
import inspect
def is_root(fun):
print 'a'
@functools.wraps(fun)
def wrapper(*args,**kwargs):
#inspect.getcallargs返回值是字典,key值为形参,value值形参对应的实参
inspect_res=inspect.getcallargs(fun,*args,**kwargs)
print 'inspec_res的返回值:%s'%inspect_res
if inspect_res.get('name')=='root':
res=fun(*args,**kwargs)
return res
else:
print 'Error:no permission'
return wrapper
login_session=['root','admin','redhat']
def is_login(fun):
print 'b'
@functools.wraps(fun)
def warrper(*args,**kwargs):
if args[0] in login_session:
res=fun(*args,**kwargs)
return res
else:
print '%s 未登陆'%args[0]
return warrper
@is_login
@is_root
def add_student(name):
print '添加学生信息'
add_student('root')
##带有参数的装饰器
import functools
import time
def log(kind):
def add_log(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
start_time=time.time()
res=fun(*args,**kwargs)
end_time=time.time()
print '<%s>[%s]函数名:%s,运行时间:%.6f,运行返回结果:%d'%(kind,time.ctime(),fun.__name__,end_time-start_time,res)
return res
return wrapper
return add_log
@log('westos')
#log ('dubug)-->返回值是add_log
#add=add_log(add)
def add(x,y):
time.sleep(1)
return x+y
print add(2,3)
编写装饰器required_types,条件如下:
1)当装饰器为@required_type(int,float)确保函数接收到的每一个参数都是int或者float类型
2)当装饰器为@required_type(list)确保函数接收到的每一个参数都是list类型
3)当装饰器为@required_type(int,str)确保函数接收到的每一个参数都是int或者str类型
4)如果参数不满足条件,打印TypeError:参数必须为xxxx类型
import functools
def required_types(*kinds):
def required_ints(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
for i in args:
if not isinstance(i,kinds):
print 'TypeError:参数必须为',kinds
break
else:
res=fun(*args,**kwargs)
return res
return wrapper
return required_ints
@required_types(float,int)
def add(a,b):
return a+b
print add(1,2.3)
##官方库
import time import math
time.tme() import os print os.listdir('/var/log')
time.ctime()
time.sleep(2) import string
import random random.sample(string.ascii_lettters,4)
random.random() random.shuffle(list(range(1,10)))
random.randint(1,4)
random.choice('hello')
##下python中的软件 pip3 install qrcode
which pip3 (/usr/local/python3/bin/pip3)
/usr/local/python3/bin/pip3 install qrcode
##第三方模块的导入,在python3.6中去做
import qrcode
#img=qrcode.make('hello world')
img=qrcode.make('http://www.baidu.com')
img.save('hello.png')
import itchat
import time
import random
while True:
##如果加上参数hotReload=True,就会保留登陆状态,在短时间内重新登陆不用再次扫描二维码
#该参数在当前目录生成一个静态文件itchat.pkl用于存储登陆状态
itchat.auto_login(hotReload=True)
#给手机助手发送消息
#itchat.send('hello',toUserName='filehelper')
itchat.send_file('/etc/passwd',toUserName='filehelper')
time.sleep(random.randint(1,3))
#2.统计你的好友的男女比例
itchat.auto_login(hotReload=True)
friends=itchat.get_friends()
#friends是一个列表数据类型,其中第一个是自己的信息,其他的都是你好友的信息
print (friends)
info={}
for friend in friends[1:]:
if friend['Sex']==1:
info['male']=info.get('male',0)+1
elif friend['Sex']==2:
info['famle']=info.get('famle',0)+1
else:
info['other']=info.get('other',0)+1
print(info)
import itchat
import random
import time
import requests
def get_tuling_response(_info):
print(_info)
##图灵机器人的api网址
api_url='http://www.tuling123.com/openapi/api'
data={
'key':'bdda1905dff245f4a420868f65dbbb13',
'info':_info,
'userid':'westoswb'
}
#发送数据到指定的网址,获取网址返回的数据
res=requests.post(api_url,data).json()
print(res['text'])
return res['text']
#时刻监控好友发送的文本信息,并给予一个回复
@itchat.msg_register(itchat.content.TEXT,isFriendChat=True)
def text_reply(msg):
#获取好友发送的消息内容,返回同样的文本信息
content=msg['Content']
#将好友的消息发送给机器人去处理
returnContent=get_tuling_response(content)
time.sleep(random.randint(1,10))
return returnContent
itchat.auto_login(hotReload=True)
#绑定消息响应事件后,让itchat运行起来
itchat.run()
#在python里面执行shell命令
##第一种方式:可以判断命令是否执行成功;返回值为0,执行成功,返回值不为0,不成功
##res=os.system('hostnames')
##print(res)
##第二种方式:用来保存命令的执行结果
##res=os.popen('hostnames').read()
##print(res)
import os
import itchat
res=os.popen('hostname').read()
print(res)
@itchat.msg_register(itchat.content.TEXT)
def text_reply(msg):
“”“
需求:当文件助手发送消息,执行发送的内容
如果执行成功:显示执行成功,执行结果,反之,显示执行失败
”“”
print(msg)
if msg['ToUserName']=='filehelper':
#获取要执行的命令的内容
command=msg['Content']
print(command)
#让电脑执行命令代码
#如果执行成功,返回值为0
if os.system(command)==0:
res=os.popen(command).read()
result='[返回值]-命令执行,执行结果:\n'+res
itchat.send(result,'filehelper')
#命令执行失败
else:
result='[返回值]-命令%s执行失败'%command
itchat.send(result,'filehelper')
itchat.auto_login(hotReload=True)
itchat.run()