您好,欢迎来到二三四教育网。
搜索
您的当前位置:首页装饰器

装饰器

来源:二三四教育网

写在前面

首先理解下,python的装饰器@mydec是一个语法糖,它的本质是func = mydec(func),也就是说把函数func作为参数传入在mydec中。

引子

假设一个函数要打印用户的姓名、年龄、性别当然还有其他Blablabla…

def print_human_information(name, age, sex):
    print("name is {}, age is {}, sex is {}.".format(name, age, sex))
    
if __name__ == "__main__":
    print_human_information(name="Lee", age=-10, sex='unknown')

然后突然你想看下这个函数执行花了多少时间,可能你会这么写:

import time

def print_human_information(name, age, sex):
    start = time.clock()
    
    print("name is {}, age is {}, sex is {}.".format(name, age, sex))
    
    end = time.clock()
    print "execute in {:.2f} ms".format((end - start) * 1000)
    
if __name__ == "__main__":
    print_human_information(name="Lee", age=-10, sex='unknown')

增加一个start,一个end,完美!
但是,如果再有一个函数不打印human,打印animal呢?Ctrl+C、V?太low逼!我们有更好的办法解决这个问题。

import time

def timeused(function):
    def wrapper(name, age, sex):
        start = time.clock()
        
        function(name, age, sex)
        
        end = time.clock()
        print "execute in {:.2f} ms".format((end - start) * 1000)
    return wrapper
        
def print_human_information(name, age, sex):
    print("name is {}, age is {}, sex is {}.".format(name, age, sex))

# 看这里,看这里,看这里
# 重要的事情说三遍
print_human_information = timeused(print_human_information)    
    
if __name__ == "__main__":
    print_human_information(name="Lee", age=-10, sex='unknown')

现在只要有了print_human_information = timeused(print_human_information)main函数中不需要做任何修改就可以显示函数执行的时间,接着让我们再来一个更简洁的语法。

@timeused
def print_human_information(name, age, sex):
    …

完美!

进阶

现在打印animal的函数真的来了,然而参数个数只有两个:

@timeused
def print_animal_information(name, age):
    print("name is {}, age is {}.".format(name, age))

好吧,timeused报错了,修改内嵌函数以及function的参数形式如下,支持任意多个参数:

def timeused(function):
    def wrapper(*args, **kwargs):
        start = time.clock()

        function(*args, **kwargs)
        
        end = time.clock()
        print "execute in {:.2f} ms".format((end - start) * 1000)
    return wrapper

God祥曾经教导我们:

一旦满足了某个需求,那么接下来类似的需求就会接踵而至。

很快,我们需要一个装饰器来检查print_human_informationprint_animal_informationagesex的合法性。(如年龄不能为负数,人类性别只能是male或者female,而对于动物我们不关心,因此该项不检查)
或许,现在是时候编写一个包含参数的装饰器了!

# 默认不检查年龄和性别
def check(check_age = False, check_sex = False):
    def wrapper(function):
        def _wrapper(*args, **kwargs):
            
            if check_age:
                _age = kwargs['age']
                if _age < 0 or _age > 140:
                    print "invalid age '{}', use default {}.".format(_age, 0)  
                    kwargs['age'] = 0
            
            if check_sex:
                _sex = kwargs['sex']
                if _sex != 'male' or _sex != 'female':
                    print "invalid sex '{}', use default {}.".format(_sex, 'male')
                    kwargs['sex'] = 'male'
                    
            function(*args, **kwargs)
            # 用于展示装饰器嵌套的效果
            time.sleep(0.5)
            
        return _wrapper
    return wrapper

@check(check_age = True, check_sex = True)
@timeused
def print_human_information(name, age, sex):
    …
    
@timeused 
@check(check_age = True)
def print_animal_information(name, age):
  …

资料

Copyright © 2019- how234.cn 版权所有 赣ICP备2023008801号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务