Python-详解装饰器及反射原理

一、装饰器

装饰器:装饰函数和类,作用:扩展增加函数和类的功能

二、装饰器的分类

两大类:装饰器函数和装饰器类

三、装饰器函数定义及应用

函数: 封装代码最小单元,提供代码复用性

  • 装饰器函数利用函数的一些特征:
    1. 函数可以用为参数;

    2. 函数可以作为变量;

    3. 函数也可以返回函数;

  • 装饰器函数可以装饰所有的函数(有参数,没参数)
import time


def runTime(func):
    """
    装饰函数
    原来功能 + 扩展的功能: 统计每个函数的耗时
    :param func:
    :return:
    """
    def wrapper(*args,**kwargs):
        start = time.time()
        #原来功能
        func(*args, **kwargs)
        end = time.time()
        cost = end - start
        print(f"统计函数使用时长:{func.__name__}耗时{cost}s")
    return wrapper

  
@runTime
def test_no_params():
    print("这是一个无参数的装饰器测试")
    
    

@runTime
def test_have_params(*args,**kwargs):
    sum = 0
    for num in args:
        sum += num
    print(f"求和: {sum}")
    return sum

  
test_no_params()
test_have_params(2,4,3,5,6,8,9)

四、装饰器类

装饰器类的实质:

调用装饰类中的__call__内置函数

import time


#定义装饰器类  ------>本质类 作用: 原来功能 + 扩展功能
class Dec:
    #原来功能 self._func()
    def __init__(self,func):
        self._func = func
    
    #扩展功能
    def __call__(self, *args, **kwargs):
        """
        __call__函数: 实例化对象()
        :param args: 
        :param kwargs: 
        :return: 
        """
        start = time.time()
        #原来功能
        self._func()
        end = time.time()
        cost = end - start
        print(f"该函数{self._func.__name__}耗时: {cost}s")
        return cost

@Dec
def test_no_param():
    """被装饰器函数"""
    print("测试函数无参数")
    time.sleep(2)

@Dec
def test_have_param(*args,**kwargs):
    """被装饰器函数"""
    sum = 0
    for i in args:
        sum += i
    print(f"sum函数耗时: {sum}s")
    time.sleep(1)

print(test_no_param())
print(test_have_param([1,4,6,3,7,9]))

五、装饰器应用场景

常见的场景:授权及日志的收集、认证等

"""
 1、编写装饰器,为多个函数加上认证的功能,要求登录成功一次,后续的函数都无需再输入用户名和密码
"""

FALG = False
def login(user,passwd):
    with open(file='admin',mode='r',encoding='utf-8') as f:
        if f.readline().strip() == user and f.readline().strip() == passwd:
            return True
        return False

def certification(func):
    def wrapper(*args, **kwargs):
        global FALG
        if FALG:
           res = func(*args, **kwargs)
        else:
            user = input("请输入用户名:")
            password = input("请输入密码: ")
            if login(user,password):
                print("登录成功")
                res = func(*args, **kwargs)
                FALG = True
            else:
                print("登录失败")
                return
        return res
    return wrapper

@certification
def shop_add():
    print("增加一个商品")

@certification
def shop_del():
    print("删除一个商品")

shop_add()
shop_del()



"""
2.编写装饰器,为多个函数加上记录调用功能,要求每次调用都将被调用的函数名写入文件
"""

def log(func):
    def wrapper(*args, **kwargs):
        with open(file="admin", mode="a", encoding="UTF-8") as file:
            file.write(func.__name__ + '\n')
        res = func(*args, **kwargs)
        return res
    return wrapper

@log
def shop_1():
    print("这是商店1")

@log
def shop_2():
    print("这是商店2")


shop_1()
shop_2()


六、反射

把字符串映射到实例的变量或者实例的方法,然后可以进行调用、修改操作

反射四个重要的方法:

  1. getattr   获取运动象属性/方法

  2. hasattr  判断对象是否有对应的属性

  3. delattr  删除指定属性

  4. setattr 为对象设置内容

 

posted @ 2021-08-13 13:56  美女爱找茬  阅读(356)  评论(0编辑  收藏  举报