ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python装饰器

2022-05-09 16:03:30  阅读:146  来源: 互联网

标签:return python args func kwargs print 装饰 def


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

闭包

闭包是什么

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

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有