编程语言
首页 > 编程语言> > python装饰器

python装饰器

作者:互联网

本文从闭包讲起,讲了闭包的定义和作用。接下来用代码介绍了装饰不带参数、带一个参数、多个参数函数,以及装饰器本身带参数的装饰器。最后举例说明了装饰器在实际编码中的应用。

闭包

闭包是什么

闭包就是能够读取外部函数内的变量的函数,如下代码:

def fun1():
    x = 1
    def fun2():
        print(x)
    return fun2

test = fun1()
test()

输出:
1
说明fun2可以读取到fun1的变量

闭包的作用

  1. 内部函数读取外部函数的变量
  2. 外部函数的变量始终维持在内存中,如下代码:
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!

原函数带参数的装饰器

  1. 带一个参数
    如下被装饰的函数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?
  1. 带多个参数
    如下被装饰的函数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