装饰器

作者: elon | 来源:发表于2016-03-12 19:56 被阅读40次

写在前面

首先理解下,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):
  …

资料

Python装饰器学习(九步入门)
PEP 0318 -- Decorators for Functions and Methods
PythonDecoratorLibrary

相关文章

  • 装饰器

    """@装饰器- 普通装饰器- 带参数的装饰器- 通用装饰器- 装饰器装饰类- 内置装饰器- 缓存装饰器- 类实现...

  • typescript 五种装饰器

    装饰器类型 装饰器的类型有:类装饰器、访问器装饰器、属性装饰器、方法装饰器、参数装饰器,但是没有函数装饰器(fun...

  • python——装饰器详解

    一、装饰器概念 1、装饰器 装饰器:一种返回值也是一个函数的函数,即装饰器。 2、装饰器目的 装饰器的目的:装饰器...

  • Python装饰器

    Python装饰器 一、函数装饰器 1.无参装饰器 示例:日志记录装饰器 2.带参装饰器 示例: 二、类装饰器 示例:

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • 装饰器

    装饰器 decorator类装饰器 带参数的装饰器 举例(装饰器函数;装饰器类;有参与无参) https://fo...

  • TypeScript装饰器

    前言 装饰器分类 类装饰器 属性装饰器 方法装饰器 参数装饰器需要在tsconfig.json中启用experim...

  • python之装饰器模版

    装饰器的作用:装饰器即可以装饰函数也可以装饰类。装饰器的原理:函数也是对象 1.定义装饰器 2.使用装饰器假设de...

  • 装饰器实验

    装饰器实验 说明 ts内包含了四个装饰器,类装饰器、属性装饰器、函数装饰器、参数装饰器,本文中测试一下其的使用。 ...

  • python3基础---详解装饰器

    1、装饰器原理 2、装饰器语法 3、装饰器执行的时间 装饰器在Python解释器执行的时候,就会进行自动装饰,并不...

网友评论

      本文标题:装饰器

      本文链接:https://www.haomeiwen.com/subject/rihbkttx.html