zoukankan      html  css  js  c++  java
  • 流畅的python--装饰器

    装饰器:以某种方式增强函数。
    两大特性:1、可以将被装饰的函数替换成其他函数。
    2、在加载模块时立即执行。

    案例1
    def make_avarage():
    count=0
    total=0
    def averager(new_value):
    count+=1
    total+=new_value
    return total/count
    return averager
    这里会报错,averager里面是一个新的 count、total变量


    案例2
    使用nolocal作用:将变量标记为自由变量,
    def make_avarage():
    count=0
    total=0
    def averager(new_value):
    nonlocal count,total
    count+=1
    total+=new_value
    return total/count
    return averager


    案例3

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    Created on Sun May  3 23:27:22 2020
    
    @author: root
    """
    
    
         promos=[]
         def promotion(promo_func):
             promo.append(promo_func)
             return promo_func
    
         @promotion
         def  FidelityPromo(order):
              return order.total()*0.05 if order.customer.fidelity>=1000 else 0
    
         @promotion
         def BulkItemPromo(order):
             discount = 0
             for item in order.cart:
                 if item.quantity>=20:
                    discount+=item.total()*0.1
             return discount
    
        @promotion 
        def LargeOrderPromo(order):
            discount_items = {item.product for item in order.cart}
            if len(discount_items)>=10:
               return order.total()*0.07
            return 0
        
        def best_promo(order):
            return max(promo(order) for promo in promos)
    
    
    二、@property:方法伪装属性,方法返回值及属性值,被装饰方法不能有参数,必须实例化后调用,类不能调用
    #@ property
    #将一个方法伪装成属性,被修饰的特性方法,内部可以实现处理逻辑,但对外提供统一的调用方式,实现一个实例属性的

    getter
    setter
    d elete
    三种方法的内部逻辑,具体含义看示
    class Data:
    
        def __init__(self):
           self.number = 123
    
        @property
        def operation(self):
           return self.number

    @operation
    .getter
    def operation(self):
    return self.number
    @operation.setter
    def operation(self, number): self.number = number @operation.deleter def operation(self): del self.number
    
    
    案例1----普通写法
    class Student(object):
    def get_score(self):
    return self._score

    def set_score(self,value):
    if not isinstance(value,int):
    raise ValueError('pppppp')
    if value < 0 or value > 100:
    raise ValueError('score must between 0 ~ 100!')
    self._score = value


    Python内置的@property装饰器就是负责把一个方法变成属性调用
    案例1----装饰器写法



    class Student(object):

        @property
        def score(self):
            return self._score

        @score.setter
        def score(self, value):
            if not isinstance(value, int):
                raise ValueError('pppppp')
            if value < 0 or value > 100:
                raise ValueError('score must between 0 ~ 100!')
            self._score = value
    s=Student()
    s.score=60
    s.score=9999
    print (s.score)

    三、类装饰器:类装饰器使用地方较少,核心是通过复写类的回调方法call.

    装饰器应用场景:

    1、引入日志
    2、函数执行时间统计
    3、执行函数前预备处理
    执行函数后清理功能
    权限校验等场景
    缓存

    方法:__call__
    __call__ 方法,不得不先提到一个概念,就是可调用对象(callable),我们平时自定义的函数、内置函数和类都属于可调用对象,但凡是可以把一对括号()应用到某个对象身上都可称之为可调用对象,判断对象是否为可调用对象可以用函数 callable
    class Add:

    def __init__(self, fn):
    print("初始化")
    self.num = 44
    self.fn = fn

    def __call__(self, *args, **kwargs):
    print("类装饰器开始工作")
    return self.fn(self.num)

    @Add
    def test(n):
    return 4+n

    if __name__ == '__main__':
    num = test()
    print(num)



    结果:
    初始化
    <function test at 0x7f95f883bc20>
    类装饰器开始工作
    44
    48
     
     

     案例1

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    Created on Mon May  4 22:11:44 2020
    
    @author: root
    简单注册表
    """
    
    
    funcs = []
    def register(func):
        funcs.append(func)
        return func
        
        
    @register
    def a():
        return 3
        
    @register
    def b():
        return 5
    
    def c():
        return 8   
    
    # 访问结果
    result = [func() for func in funcs]
    print(funcs)
    print(result)
    
    # [<function a at 0x7f95f8837050>, <function b at 0x7f95f8837290>]
    # [3, 5]

    案例2

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    Created on Mon May  4 22:14:37 2020

    @author: root

    注册表隔离(使用类的不同实例)
    """


    class Registry(object):
        def __init__(self):
            self._funcs=[]

        def register(self,func):
            self._funcs.append(func)

        def run_all(self):
            return [func() for func in self._funcs]

    r1=Registry()
    r2=Registry()


    @r1.register
    def a():
        return 3


    @r2.register
    def b():
        return 5




    案例3

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    Created on Mon May  4 22:30:41 2020
    
    @author: root
    
    用户验证
    """
    
    
    from functools import wraps
    
    class User(object):
        def __init__(self, username, email):
            self.username = username
            self.email = email
            
    class AnonymousUser(object):
        def __init__(self):
            self.username = self.email = None
            
        def __nonzero__(self):  # 将对象转换为bool类型时调用
            return False
            
        
    def requires_user(func):
        @wraps(func)
        def inner(user, *args, **kwargs):  # 由于第一个参数无法支持self, 该装饰器不支持装饰类
            if user and isinstance(user, User):
                return func(user, *args, **kwargs)
            else:
                raise ValueError("非合法用户")
        return inner
    
    
    a=User('teddy', '120@163.com')
    print (a)

    案例3

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    Created on Mon May  4 22:36:47 2020
    
    @author: root
    
    异常捕获
    """
    
    
    import json
    from functools import wraps
    
    class Error1(Exception):
        def __init__(self, msg):
            self.msg = msg
        def __str__(self):
            return self.msg
            
    
    def json_output(func):
        @wraps(func)
        def inner(*args, **kwargs):
            try:
                result = func(*args, **kwargs)
            except Error1 as ex:
                result = {"status": "error", "msg": str(ex)}
            return json.dumps(result)
        return inner
    
    # 使用方法
    @json_output
    def error():
        raise Error1("该条异常会被捕获并按JSON格式输出")

    案例3

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    Created on Mon May  4 22:40:47 2020
    
    @author: root
    
    日志管理
    ""
    
    import time
    import logging
    from functools import wraps
    
    def logged(func):
        @wraps(func)
        def inner(*args, **kwargs):  # *args可以装饰函数也可以装饰类
            start = time.time()
            result = func(*args, **kwargs)
            exec_time = time.time() - start
            logger = logging.getLoger("func.logged")
            logger.warning("{} 调用时间:{:.2} 执行时间:{:.2}s 结果:{}".format(func.__name__, start, exec_time, result))
    资源清理#import pymysql
    
    class DBConnection(object):
        def __init__(self, *args, **kwargs):
            self.args,self.kwargs = args, kwargs
            
        def __enter__(self):
            self.conn = pymysql.connect(*args, **kwargs)
            return self.conn.cursor()
            
        def __exit__(self, exc_type, exc_instance, trackback):
            self.conn.close()
     案例来源:https://www.cnblogs.com/superhin/p/11454823.html
  • 相关阅读:
    redis 简单整理——redis shell[九]
    redis 简单整理——慢查询[八]
    redis 简单整理——redis 的键管理[七]
    redis 简单整理——redis 的集合基本结构和命令[五]
    redis 简单整理——redis 的列表基本结构和命令[四]
    redis 简单整理——redis 的有序集合基本结构和命令[六]
    redis 简单整理——redis 的哈希基本结构和命令[三]
    redis 简单整理——redis 的字符串基本结构和命令[二]
    redis 简单整理——redis 准备篇[一]
    Doris开发手记3:利用CoreDump文件快速定位Doris的查询问题
  • 原文地址:https://www.cnblogs.com/1314520xh/p/12824712.html
Copyright © 2011-2022 走看看