python装饰器
作者:互联网
本文从闭包讲起,讲了闭包的定义和作用。接下来用代码介绍了装饰不带参数、带一个参数、多个参数函数,以及装饰器本身带参数的装饰器。最后举例说明了装饰器在实际编码中的应用。
闭包
闭包是什么
闭包就是能够读取外部函数内的变量的函数,如下代码:
def fun1():
x = 1
def fun2():
print(x)
return fun2
test = fun1()
test()
输出:
1
说明fun2可以读取到fun1的变量
闭包的作用
- 内部函数读取外部函数的变量
- 外部函数的变量始终维持在内存中,如下代码:
def chess(init=[0,0]):
def move(x,y):
init[0] += x
init[1] += y
return init
return move
test = chess()
print(test(1,1))
print(test(1,1))
print(test(1,1))
输出:
[1, 1]
[2, 2]
[3, 3]
可以看到每次都基于上次坐标移动,说明init列表一直保存在内存中。
装饰器
简单装饰器
如下被装饰的函数sayHello()没有参数
def my_deco(func):
def wrapper():
print('Dude,please stand up straight and say: ')
func()
return wrapper
@my_deco
def sayHello():
print('Hello, gorgeous!')
sayHello()
输出:
Dude,please stand up straight and say:
Hello, gorgeous!
原函数带参数的装饰器
- 带一个参数
如下被装饰的函数saySomething()有一个参数
def my_deco(func):
def wrapper(message):
print('Dude,please stand up straight and say: ')
func(message)
return wrapper
@my_deco
def saySomething(message):
print(message)
saySomething('Am I cute?')
输出:
Dude,please stand up straight and say:
Am I cute?
- 带多个参数
如下被装饰的函数saySomething()有多个参数
def my_deco(func):
def wrapper(*args,**kwargs):
print('Dude,please stand up straight and say:')
func(*args, **kwargs)
return wrapper
@my_deco
def saySomething(name, message):
print(name, ' '.join(message.values()))
saySomething('Sweety',{1:'am I cute?',2:'am I gorgeous?'})
输出:
Dude,please stand up straight and say:
Sweety am I cute? am I gorgeous?
装饰器本身带参数的装饰器
如下repeat装饰器本身带参数
def repeat(num):
def my_deco(func):
def wrapper(*args, **kwargs):
for i in range(num):
print('Dude,please stand up straight and say:')
func(*args, **kwargs)
return wrapper
return my_deco
@repeat(3)
def saySomething(name, message):
print(name, ' '.join(message.values()))
saySomething('Sweety',{1:'am I cute?',2:'am I gorgeous?'})
输出:
ude,please stand up straight and say:
Sweety am I cute? am I gorgeous?
Dude,please stand up straight and say:
Sweety am I cute? am I gorgeous?
Dude,please stand up straight and say:
Sweety am I cute? am I gorgeous?
装饰器嵌套
def my_deco1(func):
def wrapper(*args, **kwargs):
print('running my_deco1')
func(*args, **kwargs)
return wrapper
def my_deco2(func):
def wrapper(*args,**kwargs):
print('running my_deco2')
func(*args, **kwargs)
return wrapper
@my_deco1
@my_deco2
def saySomething(name, message):
print(name, ' '.join(message.values()))
saySomething('Sweety', {1:'am I cute', 2:'am I cool?'})
输出:
running my_deco1
running my_deco2
Sweety am I cute am I cool?
类装饰器
class Clasdeco:
def __init__(self, func):
self.func = func
self.call_count = 0
def __call__(self, *args, **kwargs):
self.call_count += 1
print('number of call is : {}'.format(self.call_count))
return self.func(*args,**kwargs)
@Clasdeco
def saySomething(message):
print(message)
saySomething('Hi, I\'m a robot')
输出:
number of call is : 1
Hi, im a robot
saySomething('Hi, i\'m an alien')
输出:
number of call is : 2
Hi, im an alien
装饰器的应用
登录认证、鉴权
def login_required(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
userid = args[0]
if validate_with_last_login(userid):
return func(*args, **kwargs)
else:
raise Exception('user should login first!')
return wrapper
def validate_with_last_login(userid):
if userid == 'Musk':
return True
else:
return False
@login_required
def search_price(*args, **kwargs):
print(args[0]+'\'s current price is 100')
search_price('Musk')
输出:
Musk's current price is 100
校验权限
class AuthorizationErr(Exception):
def __init__(self,message, status_code):
self.message = message
self.status_code = status_code
def permission_required(*permission):
def wrapper(func):
@functools.wraps(func)
def wrap(*args, **kwargs):
if validate_user_permission(permission):
return func(*args, **kwargs)
else:
raise AuthorizationErr(
'You don not have permission to access the resource right now.',
status_code=403
)
return wrap
return wrapper
def validate_user_permission(permission):
if any(['Price' in p for p in permission]):
return True
else:
return False
@login_required
@permission_required('editPrice')
def edit_price(*args, **kwargs):
print(args[0]+'\'s current price after editing is '+str(args[1]))
edit_price('Musk', 50)
输出:
Musk's current price after editing is 50
日志记录
def print_execution_time(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
res = func(*args, **kwargs)
end = time.perf_counter()
print('{} took {} ms'.format(func.__name__,(end - start)))
return res
return wrapper
@print_execution_time
def calcSum(n):
sum_ = 0
for i in range(n):
sum_+= 1
return sum_
calcSum(100)
输出:
calcSum took 1.476599999999939e-05 ms
标签:return,python,args,func,kwargs,print,装饰,def 来源: https://www.cnblogs.com/stxz/p/16249496.html