Python 逼格满满的装饰器的初步认识
基本上各种编程语言都有装饰器,而装饰器是对原有的函数和类增加更多的功能,装饰器,顾名思义,就是增强函数或类的功能的一个函数。
- 在 Python 中“函数是一等对象” 。即函数是一种特殊类型的变量,可以和其余变量一样,可以作为参数传递给函数,也可以作为返回值返回。Python 中的整数、字符串和字典等都是一等对象。
- 函数装饰器在导入模块时立即执行,而被装饰的函数只在明确调用时运行。
好了,需要明白以上两点,划重点========装饰器是一个函数,函数是一个对象,拿到这个对象的时候,我们可以当做一个参数传递给别的函数,也可以作为返回值返回该对象,就像处理整数,字符串,字典等等数据类型一样、 在使用装饰器时,装饰器与被装饰函数调用与否没有关系,也就是说,即使你不调用被装饰函数,装饰器依然工作。简单的说,你带了一个好看的帽子,帽子是增添你的美丽,你不带帽子依然美丽。那这个帽子不是专属你的,你也可以给他人用,谁带谁美丽,仅仅是个附属的增加美丽的工具。
装饰器的表现形式是闭包函数的形式,为什么使用闭包的形式?装饰器函数相对被装饰函数来说,是新的功能函数,闭包才可以将新的功能进行封装然后传递给被装饰函数啊。=====这里也有个重点了,装饰器必定是闭包的形式,不管它是几层的函数。下面代码简单的演示:
def outer(f):
def inner(*args,**kwargs):
print('这个装饰器的功能是打印数字1',1)
f(*args,**kwargs)
print('这是一个函数对象',inner)
print('这也是一个函数对象',f)
return inner#这个对象我返回了给下面调用的函数
@outer
def func(*args,**kwargs):
print('我是被装饰函数,我执行了!!')
#func()
a=outer(func)
#执行结果:这是一个函数对象 <function outer.<locals>.inner at 0x000000000261E1F0>
#这也是一个函数对象 <function func at 0x000000000261E160>
#这是一个函数对象 <function outer.<locals>.inner at 0x000000000261E280>
#这也是一个函数对象 <function outer.<locals>.inner at 0x000000000261E1F0>
#==========================================================================
#可以发现,函数对象的内存改变了,被装饰的函数调用是被注释的情况下,
#上面的@outer执行了一遍装饰器函数,下面的a变量接收了装饰器函数又执行了一遍。
#由于是变量接收的,因此内存地址改变了。但两者功能是一致的。也就是@outer等价于 a=outer(func)
#===================================================================================
def outer(f):
def inner(*args,**kwargs):
print('这个装饰器的功能是打印数字1',1)
f(*args,**kwargs)
print('这是一个函数对象',inner)
print('这也是一个函数对象',f)
return inner#这个对象我返回了给下面调用的函数
@outer
def func(*args,**kwargs):
print('我是被装饰函数,我执行了!!')
func()
#这个是正常的装饰器以及装饰器的使用,结果自己打印看看??
以上示例的装饰器十分的简单,我想,很多人都知道旗标,旗标是控制程序的运行与中断流程的一个概念,同样的,在装饰器中,我们也可以使用旗标,来控制装饰器是否启用。下面的一个示例演示的是装饰器中的旗标使用,可以通过旗标决定是否使用装饰器,从而避免了装饰器的滥用。
import time
def time_count_plus(flag=True):
def wrap1(func):
def wrap2(*args,**kwargs):
if flag:
time_flag=time.time()
temp_result=func(*args,**kwargs)
time.sleep(1)
print(time.time()-time_flag-1)
else:
temp_result=func(*args,**kwargs)
return temp_result
return wrap2
return wrap1
@time_count_plus(flag=False)
#这是带参数的装饰器
def range_loop(a,b):
sums=1
for i in range(a,b):
sums+=i
return sums
print(range_loop(0,1010000))
#被装饰器函数是一个求累加数字和的函数,装饰器的功能是计算某个程序运行的时间,其中,time.sleep(1),以#及后面的时间减法-1是为了提高该装饰器的时间计算精度,最关键的改变在装饰器内层函数内的旗标判断以及
#装饰器引用时的旗标判断,@time_count_plus(flag=False)这行如果旗标参数为False,那么装饰器将不会
#被执行,反之,任意值都会立刻执行,执行顺序见第一个示例。
以上示例与第一个示例显著不同在该装饰器是一个带参数的装饰器,当然了,既然我们可以使用flag这个旗标做参数,我们也可以使用别的任意的东西做参数,从而根据自己的需要决定哪些被装饰函数使用装饰器,以及哪一部分使用装饰器。
高级的装饰器函数我想过几天整理下思路在写吧,比如,基于类的类装饰器,装饰器的多层嵌套,静态方法装饰器等等。先这样。