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