您的位置:首页 > 编程语言 > Python开发

Python装饰器深入理解

2019-09-07 18:00 1801 查看

1、开放封闭原则:

(1)代码扩展进行开放

​ 任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

(2)修改源代码是封闭

​ 当我们写的一个函数,已经交付给其他人使用,如果这个时候我们对函数内部进行修改,或者修改了函数的调用方式,很有可能影响其他已经在使用该函数的用户。

在不修改源代码及调用方式,对功能进行额外的添加就是开放封闭原则

2、装饰器:

在不改变原被装饰的函数的源代码以及调用方式下,为其添加额外的功能。

(1)初识装饰器:

​ 装饰(额外功能) 器(工具:函数)

import time
def index():
time.sleep(2)  #
print("这是小明写的功能")
def func():
time.sleep(1)  #
print("这是小刚写的功能")
def red():
time.sleep(2)  #
print("这是小红写的功能")
start_time = time.time()  # 时间戳
index()
print(time.time() - start_time)
start_time = time.time()  # 时间戳
func()
print(time.time() - start_time)
start_time = time.time()  # 时间戳
red()
print(time.time() - start_time)

( 此方法返回的是格林尼治时间,是此时此刻距离1970年1月1日0点0分0秒的时间秒数.也叫时间戳,它是一直变化的。)

import time
print(time.time())

以上代码重复,繁琐

改进:(将求时间写在一个函数中,函数就是以功能为导向,减少重复代码)

import time
def index():
time.sleep(2)  #
print("这是小明写的功能")
def func():
time.sleep(1)  #
print("这是小刚写的功能")
def red():
time.sleep(2)  #
print("这是小红写的功能")
def times(func):
start_time = time.time()  # 时间戳
func()
print(time.time() - start_time)
times(index)
times(func)

改进:

第一版装饰器
import time
def func():
time.sleep(1)  #
print("这是小刚写的功能")
def red():
time.sleep(2)  #
print("这是小红写的功能")
def index():
time.sleep(2)  #
print("这是小明写的功能")
def times(func):
def foo():
start_time = time.time()  # 时间戳  被装饰函数执行前干的事
func()
print(time.time() - start_time) #   被装饰函数执行后干的事
return foo           # 不能加括号
index = times(index)       # 不能加括号
index()
func = times(func)
func()

(2)语法糖 (Python 帮我们做的一个东西)

要将语法糖写在被装饰函数的最上方
def warpper(f):
def inner():
print("111")
f()
print("222")
return inner
# python帮咱们做的一个东西,语法糖
@warpper  # func = warpper(func)
def func():
print("被装饰的函数1")
@warpper  # index = warpper(index)
def index():
print("被装饰的函数2")
func()
def warpper(f):
def inner(*args,**kwargs):
print("被装饰函数执行前")
ret = f(*args,**kwargs)
print("被装饰函数执行后")
return ret
return inner
@warpper
def func(*args,**kwargs):
print(f"被装饰的{args,kwargs}")
return "我是func函数"
@warpper
def index(*args,**kwargs):
print(11111)
print(func(1,2,3,4,5,6,7,8,a=1))

(3)标准版的装饰器:

def wrapper(func):
def inner(*args,**kwargs):
'''执行被装饰函数之前的操作'''
ret = func()
'''执行被装饰函数之后的操作'''
return ret
return inner

这个就是标准的装饰器,完全符合代码开放封闭原则。

4、装饰器进阶

(1)有参装饰器

def auth(argv):
def warpper(func):
def inner(*args,**kwargs):
if argv == "博客园":
print("欢迎登录博客园")
user = input("user:")
pwd = input("pwd:")
if user == 'alex' and pwd == "dsb":
func(*args,**kwargs)
elif argv == "码云":
print("欢迎登录码云")
user = input("user:")
pwd = input("pwd:")
if user == 'alex' and pwd == "jsdsb":
func(*args, **kwargs)
return inner
return warpper
def foo():
print("被装饰的函数")
msg = input("请输入您要登录的名字:")
a = auth(msg)
foo = a(foo)
foo()
def auth(argv):
def wrapper(func):
def inner(*args,**kwargs):
if argv:
print("我加上功能了!")
func(*args,**kwargs)
else:
func(*args,**kwargs)
return inner
return wrapper
https://www.cnblogs.com/
@auth(True)   # @auth == foo = wrapper(foo) = auth(True)   flask框架
def foo():
print("这是一个点燃")
foo()

(2)多个装饰器装饰一个函数

多个装饰器装饰一个函数,先执行离被装饰函数最近的装饰器

def auth(func):             # wrapper1装饰器里的 inner
def inner(*args,**kwargs):
print("额外增加了一道 锅包肉")
func(*args,**kwargs)
print("锅包肉 38元")
return inner
def wrapper1(func):        # warpper2装饰器里的 inner
def inner(*args,**kwargs):
print("额外增加了一道 刺生")
func(*args,**kwargs)
print("刺生 白吃")
return inner
def wrapper2(func):         # 被装饰的函数foo
def inner(*args,**kwargs):
print("额外增加了一道 麻辣哥")
func(*args,**kwargs)
print("难以下嘴")
return inner
def foo():
print("这是一个元宝虾饭店")
foo = wrapper2(foo) # inner = wrapper2(foo)
foo = wrapper1(foo) # inner = wrapper1(inner)
foo = auth(foo)     # inner = auth(inner)
foo()               # auth里边的inner()
def auth(func):            # wrapper1装饰器里的 inner
def inner(*args,**kwargs):
print(123)
func(*args,**kwargs)
print(321)
return inner
def wrapper1(func):         # warpper2装饰器里的 inner
def inner(*args,**kwargs):
print(111)
func(*args,**kwargs)
return inner
def wrapper2(func):          # 被装饰的函数foo
def inner(*args,**kwargs):
print(222)
func(*args,**kwargs)
print(567)
return inner
@auth                 # 1           7
@wrapper1             #   2       6
@wrapper2             #    3    5
def foo():            #      4
print("www.baidu.com")
foo()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Python装饰器