装饰器
一、概念
1. 装饰器(Decoration):
- 装饰器是一种设计模式,经常用来实现"面向切面的编程"(AOP: 实现在不修改源代码的情况下,给程序动态添加功能的一种技术)
2. 装饰器的作用:
- 装饰器允许向一个现有的对象(函数)添加新的功能,同时又不改变其结构
- 可以抽离出大量的函数中的和业务无关的功能
3. 应用场景:
- 插入日志、性能测试、事务处理、缓存、中间件、权限控制等
举个栗子:现在需要计算某个函数的执行时间
import time
def fun1():
start = time.time()
s = 0
for i in range(1, 100001):
s += i
print(f'和为:{s}')
t = time.time() - start
print(f'函数的执行时间为:{t:.10f}')
fun1()
def fun2():
start = time.time()
s = 1
for i in range(1, 100001):
s *= i
print(f'乘积为:{s}')
t = time.time() - start
print(f'函数的执行时间为:{t:.10f}')
fun2()
如果要把计算时间的代码抽离出来,此时就可以使用装饰器来实现
import time
def get_time(func):
def wrapper():
start = time.time()
func()
t = time.time() - start
print(f'函数的执行时间为:{t}')
return wrapper
@get_time
def fun2():
s = 1
for i in range(1, 100001):
s *= i
print(f'乘积为:{s}')
fun2()
二、装饰器详解
1、装饰器
装饰器:
1. 关键字:@,在被修饰的函数的前一行加入
2. 本质:装饰器的本质就是一个函数
3. 原理:在调用被装饰的函数时,被装饰的函数体的代码并不会被直接执行。而是在调用被装饰的函数时,将该函数传递给装饰器
2、装饰器的基本形式
并不是真正的装饰器(有问题)
def my_decoration(func):
print('*'*10,'我是华丽丽的分隔线','*'*10)
return func
@my_decoration
def f():
print('这是一个函数')
f()
@my_decoration
def f2():
print('这是另一个函数')
f2()
3、装饰器-内嵌函数
并不是真正的装饰器
def my_decoration(func):
def wrapper():
print('这是要装饰的内容')
wrapper()
return func
@my_decoration
def f2():
print('这是另一个函数')
f2()
4、装饰器-闭包函数
def my_decoration(func):
def wrapper():
print('\n'+'*'*10,'start','*'*10)
func()
print('*'*11,'end','*'*11,'\n')
return wrapper
@my_decoration
def f():
print('这是另一个函数')
f()
5、装饰器闭包原理剖析
def outer(x):
def inner():
return x
return inner
ot = outer('哈哈哈')
print(ot())
def outer(x):
def inner():
x()
return inner
def f1():
print('这是f1函数')
ot = outer(f1)
ot()
def outer(func):
def inner():
print(1111111111)
func()
print(22222222)
return inner
@outer
def f2():
print('这是f2函数')
f2()
三、带参数的装饰器
之前实现的装饰器,给被装饰的函数添加的都是相同的功能,如果希望这个装饰对不同的函数作出不同的响应,此时就需要给装饰器传参数,在装饰器的内部根据参数的不同,作出不同的操作
def my_decoration(a):
def wrapper(func):
def inner():
if a < 10:
print(1111)
else:
print(2222)
func()
return inner
return wrapper
@my_decoration(a=5)
def f1():
print('这是第一个函数')
f1()
@my_decoration(a=20)
def f2():
print('这是第二个函数')
f2()
四、类装饰器
装饰器不一定只能用函数来实现,也可以使用类来装饰,用法与函数装饰器区别不大,实质上是调用了类方法中__call__魔法方法
class logging:
def __init__(self, func):
print('__init__',func)
self.__func = func
def __call__(self):
print(1111111)
return self.__func()
@logging
def hello():
print('hello 你好呀')
hello()
五、内置装饰器
Python语言本身也有一些装饰器,比如@property
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
gou = Person('二狗',18)
gou.age = 20
修改:
class Person:
def __init__(self, name, age):
self.__name = name
self.__age = age
def set_age(self, age):
if isinstance(age, int):
if 0 < age < 100:
self.__age = age
else:
raise ValueError('年龄超出范围')
else:
raise TypeError('年龄类型错误')
def get_age(self):
return self.__age
gou = Person('二狗', 18)
gou.set_age('abc')
print(gou.get_age())
再次修改:
class Person:
同上....
age = property(fget=get_age, fset=set_age)
gou = Person('二狗', 18)
gou.age = 200
print(gou.age)
@property
class Person:
def __init__(self, name, age):
self.__name = name
self.__age = age
@property
def age(self):
return self.__age
@age.setter
def age(self,a):
self.__age = a
gou = Person('二狗', 18)
gou.age = 20
print(gou.age)
@staticmethod
将类中的方法设置为静态方法,它不需要创建实例对象,就可以使用类名来调用
class Person:
x = 100
xxxxxx...... 其它代码自己补
@staticmethod
def f():
print(Person.x)
print('静态方法')
Person.f()
p = Person('Tom',18)
p.f()
@classmethod
class Person:
xxxxxxxxxxxxx..............
@staticmethod
def f():
print(Person.x)
print('静态方法')
@classmethod
def n(cls):
print(cls,type(cls))
print(isinstance(cls,Person))
print(cls.x)
Person.n()
p = Person('Tom',18)
p.n()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)