zoukankan      html  css  js  c++  java
  • python 装饰器

     装饰器

    缺陷:自定义装饰器,缺失了一些功能(比如:函数的__name__属性不正确);而使用Python标准库提供的系统提供的装饰器辅助定义函数就可以很好地解决这个问题:

    from functools import wraps

    装饰器(函数)定义要点

    l  返回值是一个函数

    l  返回的函数的内部,调用将来要被装饰的函数

    l  推荐使用functools包中的wraps 函数修饰要返回的函数,用于保留被修饰的函数的信息(比如:函数名 __name__)

    l  装饰器修饰其他函数时,使用 @装饰器函数名 的方式

    高级内容(后续项目中讲解):

    • 一个函数,可以被多个装饰器修饰装饰。
    • 装饰器可以有自己的参数。
    # 最简单的装饰器(不带参数)
    def zhuangshiqi(func):
        return lambda : func()
    
    def my_func():
        print('hello')
    # 用装饰器 zhuangshiqi 装饰函数 my_func,函数方式调用
    my_func = zhuangshiqi(my_func)
    
    my_func()
    # 简单装饰器(带参数)
    def zhuangshiqi(func):
        return lambda name: func(name) # 需要传递参数,因为被装饰的函数是有参数的
    
    def my_func(name):
        print(name)
    
    # 用装饰器 zhuangshiqi 装饰函数 my_func,函数方式调用
    my_func = zhuangshiqi(my_func)
    
    my_func('张三')
    def check(func):
        # 自定义装饰器(参数筛选功能)
        def wrapper(*nums):
            #
            origin_len = len(nums)  # 筛选前计算容器长度(元素个数)
            nums = filter(lambda num: isinstance(num, (int, float)), nums)  # 筛选
            nums = list(nums)  # 需要转化为list
            new_len = len(nums)  # 筛选前计算容器长度(元素个数)
            # 如果筛选前后,容器中元素的个数变化了,说明容器中有异常值
            if origin_len != new_len:
                print('参数有误')
            else:
                # 调用被装饰器装饰的函数
                return func(*nums)
        return wrapper
    
    @check # 应用自定义装饰器
    def calc_sum(*nums): # 定义函数
        return sum(nums)
    
    # nums = [4, 30, 200, 1000] # 正常值
    nums = [4, 30, 200, 1000, '10'] # 错误值
    # 调用函数
    print(calc_sum(*nums))
    # 自定义装饰器存在缺陷(缺陷之一:函数名指向有误)
    print(calc_sum.__name__)
    from functools import wraps # 引入系统提供的装饰器辅助定义函数
    
    # 定义装饰器
    def check(func):
        # 应用系统装饰器辅助定义函数
        @wraps(func)
        def wrapper(*nums, **kwargs):
            origin_len = len(nums)  # 筛选前计算容器长度(元素个数)
            nums = filter(lambda num: isinstance(num, (int, float)), nums)  # 筛选
            nums = list(nums)  # 需要转化为list
            new_len = len(nums)  # 筛选前计算容器长度(元素个数)
            # 如果筛选前后,容器中元素的个数变化了,说明容器中有异常值
            if origin_len != new_len:
                print('参数有误')
            else:
                # 调用被装饰的函数
                return func(*nums, **kwargs)
        return wrapper
    
    @check # 使用装饰器
    def calc_sum(*nums): # 定义求和函数
        return sum(nums)
    
    # nums = [4, 30, 200, 1000] # 正常值
    nums = [4, 30, 200, 1000, '10'] # 错误值
    # 调用函数
    print(calc_sum(*nums))
    # 最简单的标准装饰器
    from functools import wraps # 引入系统提供的装饰器辅助定义函数
    
    # 定义装饰器
    def zhuangshiqi(func):
        # 应用系统装饰器辅助定义函数
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 调用被装饰的函数
            return func(*args, **kwargs)
        return wrapper
    
    @zhuangshiqi # 使用装饰器
    def my_func(name): # 定义函数
        print(name)
    
    my_func('张三') # 调用函数
    print(my_func.__name__) # 获取函数名

  • 相关阅读:
    MySql设计表中的create_time和update_time字段
    java.lang.NoSuchMethodError: scala.Product.$init$(Lscala/Product;)V
    Hbase问题:java.lang.RuntimeException: HRegionServer Aborted
    Elasticsearch 7.6.2 简单的api(springboot)
    idea + springboot 热部署
    kibana Elasticsearch cluster did not respond with license information.
    Elasticsearch7.6.2 搭建的坑
    数据库账号密码加密
    pg数据库,插入数据,若已存在则更新数据
    org.postgresql.util.PSQLException:这个 ResultSet 已经被关闭。
  • 原文地址:https://www.cnblogs.com/sxqfuture/p/9390887.html
Copyright © 2011-2022 走看看