zoukankan      html  css  js  c++  java
  • python装饰器终极奥义

    python装饰器终极奥义

    python装饰器

    定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能
    原则:
    1. 不能修改被装饰的函数的源码
    2. 不能修改原函数的调用方式
    知识储备: 1. 函数即变量 函数执行的时候解释器从上向下执行 2. 高阶函数
    a. 把一个函数名当作实参传递给另一个函数(可以做到在不修改函数源码的情况下,为其添加功能) b. 返回值中包含函数名 3. 嵌套函数
    当装饰器需要参数需要三层嵌套,不需要参数两层嵌套

    装饰器可能的应用

    作为一个函数

    创造装饰器最简单的方法就是写一个函数,返回包装原始函数调用的一个子函数

    def mydecorator(function):  
        def wrapped(*args,**kwargs):  
            #调用原始函数之前做的操作  
            result=function(*args,**kwargs)  
            #调用原始函数之后做点什么  
            #返回结果  
            return result  
        #返回wrapper作为装饰函数  
        return wrapped
    

    作为一个类

    大多数情况装饰器总是用函数实现,但在某些情况下使用类会更好。如果装饰器需要复杂的参数化或者依赖特定状态,就会使用装饰类
    通用模式

    class DecoratorAsClass:  
    def __init__(self,function):
    self.function=function
    def __call__(self,*args,**kwargs):
    #在调用原始函数指点,做点什么
    result=self.function(*args,**kwargs)
    #在调用原始函数之后做点什么
    #返回函数执行结果
    return result
    @DecoratorAsClass
    def hello():
    print('hello')
    hello()

    参数化装饰器

    实际使用装饰器需要使用参数化的装饰器。类装饰器不用说,初始化的时候就可以传入参数。如果是函数作装饰器的话,就需要第二层包装。如需要多次执行一个原始函数,而重复次数通过装饰器参数给定,下面是示例代码

    def repeat(number=3):  
    """多此执行装饰函数,返回最后一次执行结果
    参数名为 number:重复次数,默认为3
    """
    def erceng_decorator(function):
    def wrapper(*args,**kwargs):
    result=None
    for _ in range(number):
    result=function(*args,**kwargs)
    return result
    return ercent_decorator
    @repeat(2)
    def hello():
    print("hello")
    hello()
    hello
    hello

    在使用参数化装饰器的时候参数有默认值,但名字后面必须加括号,否则会报错

    保存内省的装饰器

    在使用装饰器常见的问题就是无法保存原始函数的元数据(文档字符串和函数名),装饰器组合创建了一个新的函数,返回一个新的对象,但没有考虑到原始函数的标识。这回给调试造成麻烦,无法找寻原始函数,也会破坏自动生成文档的工具,无法访问原始函数的文档字符串

    def dummy_dec(function):
    ... def wrapped(*args,**kwargs):
    ... """包装函数内部文档。"""
    ... return wrapped
    @dummy_dec
    ... def function_important_doc():
    ... """这是重要文档"""
    function_important_doc.__name__
    'wrapped'
    >>> function_important_doc.__doc__
    '包装函数内部文档。'

    如上所示,原始函数的名字和文档都被修改了,解决这个问题也很容易,使用functools模块内置的wraps()装饰器:

    from functools import wraps  
    def chuli_dec(function):
    @wraps(function)
    def wrapper(*args,**kwargs):
    """包装函数文档"""
    return function(*args,**kwargs)
    return wrapper
    @chuli_dec
    def func_import_doc():
    """这是重要文档"""
    print(func_import_doc.__name__)
    print(func_import_doc.__doc__)
    func_import_doc
    这是重要文档

    像上面处理这就对了

  • 相关阅读:
    11.11 ntsysv:管理开机服务
    11.13 ethtool:查询网卡参数
    11.14 mii-tool:管理网络接口的状态
    11.15 dmidecode:查询系统硬件信息
    11.16-18 lsci、ipcs、ipcrm:清除ipc相关信息
    Devops 导论
    * SPOJ PGCD Primes in GCD Table (需要自己推线性筛函数,好题)
    SPOJ
    HDU 1695 莫比乌斯反演
    HDU 1800 hash 找出现最多次数的字符串的次数
  • 原文地址:https://www.cnblogs.com/dcotorbool/p/8158008.html
Copyright © 2011-2022 走看看