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()

 

 

 

posted @ 2019-11-04 17:24  不休不止  阅读(681)  评论(2编辑  收藏  举报