装饰器: 器,函数;实质上是用来装饰函数的函数
产品经理和开发人员
1. 定义万能装饰器
def 装饰器名称(f):
def wrapper(*args, **kwargs):
# 函数执行之前的操作
f(*args, **kwargs)
# 函数执行之后的操作
return wrapper
def 装饰器名称(f):
def wrapper(*args, **kwargs):
if 条件:
f(*args, **kwargs)
else:
# 报错并抛出异常 raise Error("xxxxxx")
return wrapper
2. 有参数的装饰器
def 有参数的装饰器(*args, **kwargs):
def 装饰器名称(f):
def wrapper(*args, **kwargs):
if 条件:
f(*args, **kwargs)
else:
# 报错并抛出异常 raise Error("xxxxxx")
return wrapper
return 装饰器名称
3. 装饰器底层原理
@timmer # fun = timmer(fun)
def fun():
pass
4. functools: 保留原有函数的名称(f.name)和文档帮助等信息;
def 装饰器名称(f):
@functools.wrap(f)
def wrapper(*args, **kwargs):
if 条件:
f(*args, **kwargs)
else:
# 报错并抛出异常 raise Error("xxxxxx")
return wrapper
5. inspect:
不管是默认参数, 必选参数, 可变参数, 关键子参数, 都会将形式参数和传的值封装为字典;便于使用;
"""
**例子1:
# 装饰器: 本质上是一个函数, 接收其他函数作为参数;对于原有的函数做了新的修改;
import random
import time
def addInfo(fun): # fun: transferMoney
def wrapper():
print "六一儿童节快乐...."
fun() # transferMoney()
print fun.__name__
print "欢迎使用ICBC ATM......."
return wrapper
# python的语法糖:for i in s:
@addInfo
# transferMoney = addInfo(transferMoney) # 返回wrapper
def transferMoney():
print "转账......."
# wrapper
transferMoney()
**例子2:
计时器
import random
import time
import functools
def timmer(fun): # fun = login
# 这个@functools.wraps(fun)可以保留函数原有的函数名和函数帮助文档;
@functools.wraps(fun)
def wrapper(*args, **kwargs):
"""this is wrapper"""
# args: tuple
# kwargs: dict
# 获取当前时间戳i
start_time = time.time()
# *args对元组进行解包;
# **kwargs对字典进行解包的;
fun(*args, **kwargs) # fun() ==== login()
end_time = time.time()
# 任何一个函数都有一个属性__name__,获取函数名称;
print "%s 执行时间为%s" %(fun.__name__, end_time-start_time)
return wrapper
@timmer
def fun1():
print "func1....."
# time.sleep: 休眠
# random.random: 随即生成一个0~1之间的数;
time.sleep(random.random())
@timmer
# login = timmer(login)
def login(name, password):
""" user login
"""
if name == 'root' and password == 'redhat':
print 'login ok'
else:
print 'login fail'
if __name__ == "__main__":
login('root', 'westos')
print login.__name__
print login.func_doc
**例子3:
多个装饰器
def makebold(fn):
def wrapper():
return "<b>" + fn() + '</b>'
return wrapper
def makeitalic(fn):
def wrapper():
return "<i>" + fn() + "</i>"
return wrapper
@makebold # <b>"hello world"</b>
@makeitalic # <i><b>"hello world"</b></i>
def hello():
return "hello world"
if __name__ == "__main__":
print hello()
**例子4:
def counter(f):
def wrapper(*args, **kw):
wrapper.count += 1
f(*args, **kw)
print "%s has been used %s" %(f.__name__,wrapper.count)
wrapper.count = 0
return wrapper
@counter
def fun():
print "fun......."
@counter
def fun1():
print "fun1......."
f1 = fun()
f2 = fun()
f3 = fun()
f4 = fun()
f5 = fun()
**例子5:
给装饰器传参
import random
import time
def add(name): # name = "转账
def addInfo(fun): # fun: transferMoney
def wrapper():
print "六一儿童节快乐...."
fun() # transferMoney()
print fun.__name__
print "欢迎使用ICBC ATM...%s模块...." %(name)
return wrapper
return addInfo
@add("转账") # add = add("转账")
def transferMoney():
print "欢迎来到ATM....."
@add("存钱") # add = add("转账")
def saveMoney():
print "欢迎来到ATM....."
transferMoney()
saveMoney()
**例子6:
import functools
def required_type(*args_type):
# args_type: tuple
def required_num(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
# args:tuple
# kwargs:
# kwargs.values(): list
for arg in args + tuple(kwargs.values()):
print args_type
if not isinstance(arg, args_type):
# 抛出异常
# f.__name__函数的名称
raise TypeError("[参数错误]: %s only accept nums as arguments;" % (f.__name__))
#f: 是函数名, f():调用函数
return f(*args, **kwargs)
return wrapper
return required_num
@required_type(int, float)
def add(a, b):
return a + b
print add(5, 1.0)