zoukankan      html  css  js  c++  java
  • Python装饰器的使用

    对于python编程人员,装饰器的使用肯定是必不可少的。

    装饰器分为系统定义装饰器和自定义装饰器;系统定义装饰器:@classmethod:类方法装饰器  @staticmethod:   静态方法装饰器   @property修饰的方法是属性方法,属性方法被调用时不需要在方法后加括号 详细请参考python内置装饰器的使用。

    装饰器的本质就是一个函数,作用是在不改变源代码的情况下,给函数增加额外的功能;装饰器的使用通过@语法糖进行调用

    自定义装饰器又分为:带参的装饰器和不带参的装饰

    先来说不带参的装饰器:

    # 1.声明一个普通的装饰器
    # 需求:获取每个函数的运行时间
    import datetime,time
    
    def get_func_time(func): # 外层作为装饰函数,必须接收参数,将被装饰函数传入
        def inner(*args):         # 内层实现被装饰函数的额外功能,如果被装饰函数需要传入参数,可以定义不定长参数:*args,或者关键字参数:**kwargs
            start_time = datetime.datetime.now()      # 获取当前时间,作为开始时间
            result = func(*args)           # 调用传入的被装饰的函数,传入需要的参数
            end_time = datetime.datetime.now()        # 获取当前时间,作为结束时间
            print('程序的运行时间为:', end_time - start_time)
            return result    # 如果被装饰函数是有返回值的,在此也应该将结果进行返回
        return inner         # 必须将内层函数对象返回,如果不返回会报:typeError
    

    @get_func_time def program(): #该函数不需要传入参数 # 被装饰函数,实现休息三秒 time.sleep(3)
    # 调用函数:
    program()

    程序的执行结果
    @get_func_time
    def get_max_common_divisor(num1,num2): # 这是一个需要传入参数的函数
        '''
        求两数的最大公约数
        '''
        max_common_divisor = 0
        min_num = min(num2,num1)
        for i in range(1,min_num+1):
            if num1 % i == 0 and num2 % i ==0:
                print('这是一个公约数:',i)
                max_common_divisor = i
        return max_common_divisor


    # 调用函数:
    get_max_common_divisor(20, 10)

    然后我们写一个带有参数的装饰器:

    # 需求实现打印不同花边的姓名
    
    # 如果需要声明一个带有参数的装饰器,则需要嵌套三层函数,最外层进行选择判断。
    def decorator(choice):
        if choice == '*':
            def out(func):
                def inner(*args):
                    print('**********')
                    func(*args)
                    print('**********')
                return inner
            return out
        elif choice  == '-':
            def out(func):
                def inner(*args):
                    print('----------')
                    func(*args)
                    print('----------')
                return inner
            return out
        else:
            def decorator(func):
                def inner(*args):
                    print('%%%%%%%%%%')
                    func(*args)
                    print('%%%%%%%%%%')
                return inner
            return decorator
    
    
    @get_func_time          # 调用装饰器使用:@装饰器名称   # 一个函数可以调用多个装饰器
    @decorator(choice='-')
    def get_name(name):
        # 源代码:打印姓名
        print(name)
    
    get_name('刘德华')

     除了可以声明函数装饰器还可以声明一个类装饰器;如果要声明一个类装饰器必须实现__call__方法;__call__方法的使用参考下方

    # 不带参数的类装饰器类装饰器
    import time,datetime
    class class_decorator():
    
        def __init__(self,func): # __init__方法用于接收传入的函数
            self.func = func
    
        def __call__(self, *args, **kwargs): # call方法则相当于函数装饰器的内层函数
            start = datetime.datetime.now()
            self.func()
            end = datetime.datetime.now()
            return end - start
    @class_decorator
    def programs():
        print('程序开始')
        time.sleep(3)
        print('程序结束')
    
    
    
    program_time = programs()
    print('程序运行时间为:',program_time)

    # 带参数的类装饰器
    class decorator():
    
        def __init__(self,language):  # init 方法接收的不在是传入的函数,接收的是参数
            self.language = language
    
        def __call__(self,func):       # 函数通过call方法传入
            if self.language=='中文':  # 执行判断
                def inner(*agrs,**kwargs):# 内层函数增加功能
                    name = func(*agrs)
                    return '你好' + name
                return inner
            elif self.language == 'English':
                def inner(*agrs, **kwargs):
                    name = func(*agrs)
                    return 'Hello\t' + name
                return inner
    
    @decorator('English')
    def aaa(name):
        return name
    
    name = aaa('张三')
    print(name)

     补充:__call__方法的使用;__call__ 方法实现将类实例变成一个可以调用的函数

    class B():
        def __init__(self):
            print('这是初始化方法')
    
        def __call__(self):
            print('这是call方法')
    
    b = B()
    b()

  • 相关阅读:
    Java实现 LeetCode 179 最大数
    Java实现 LeetCode 179 最大数
    Java实现 LeetCode 179 最大数
    SQL Server实现 LeetCode 178 分数排名
    SQL Server实现 LeetCode 178 分数排名
    SQL Server实现 LeetCode 178 分数排名
    开源免费的C/C++网络库(c/c++ sockets library)
    C++开源跨平台类库集
    动态链接库中分配内存引起的问题-- windows已在XX.exe中触发一个断点
    SDL 简介
  • 原文地址:https://www.cnblogs.com/XhyTechnologyShare/p/11793188.html
Copyright © 2011-2022 走看看