装饰器的最大用处,就是关联操作,或者叫同步,或者叫联动。当你有几种操作需要同步时,考虑到使用装饰器,就会产生多个装饰器“位置摆放疑团”。
import sqlite3
def opendb2(f):
def operatedb(dbPath=r"C:\Users\Administrator\Desktop\107.db",*tableName):
print("trying to connect DB...")
connt = sqlite3.connect(dbPath)
print("TASK FINISHED!")
return f(connt,*tableName)
return operatedb
@opendb2
def anyfunction():
...
比如以上的数据库打开操作,当你看到其中实际执行前后都有输出提示信息,可以继续习惯性抽出装饰器里的东西,变成日志型装饰器。
import sqlite3
def tipslog(f):
def innerdo(*x):
print("trying to connect DB...")
a = f(*x)
print("TASK FINISHED!")
return a
return innerdo
def opendb2(f):
#单独看效果,或者放在本装饰器的外层,或者放在其他需要装饰之函数的外层
#然而深究起每一种位置的传入函数来,却不一样
@tipslog
def operatedb(dbPath,*tableName):
connt = sqlite3.connect(dbPath)
return f(connt,*tableName)
return operatedb
@opendb2
def any_function(any_parameter):
...
现在有两个装饰器定义了,问题也来了:(1)两个装饰器分别要摆什么位置?(2)每一种位置有什么区别?
import sqlite3
def tipslog(f):
def innerdo(*x):
print("trying to connect DB...")
a = f(*x)
print("TASK FINISHED!")
return a
return innerdo
#第二种位置,连续调用any_function时只有第一个生效。
#实际上是后面@本装饰器时已经执行了
@tipslog
def opendb2(f):
def operatedb(dbPath,*tableName):
connt = sqlite3.connect(dbPath)
return f(connt,*tableName)
return operatedb
@opendb2
def any_function(any_parameter):
...
import sqlite3
def tipslog(f):
def innerdo(*x):
print("trying to connect DB...")
a = f(*x)
print("TASK FINISHED!")
return a
return innerdo
def opendb2(f):
def operatedb(dbPath,*tableName):
connt = sqlite3.connect(dbPath)
return f(connt,*tableName)
return operatedb
@tipslog#第三种位置
@opendb2
def any_function(any_parameter):
...
当然在实际中应用,其实可以顺着自己抽象的思路,放在就近关联的位置,比如第一种摆法,像膏药一样贴着原先属于的函数,最终形成套娃。
附加题:
from time import time
import sqlite3
def time_cost(f):
def core(*x):
begin = time()
r = f(*x)
end = time()
print("耗时","{:.4f}s".format(end - begin))
return r
return core
def tipslog(f):
#@time_cost
def innerdo(*x):
print("尝试连接数据库...")
try:
a = f(*x)
print("TASK FINISHED!")
except:
a = None
print("数据库矬啦!请检查参数({})".format(x))
return a
return innerdo
def opendb2(f):
#@time_cost
@tipslog
#@time_cost
def operatedb(dbPath,*tableName):
connt = sqlite3.connect(dbPath)
return f(connt,*tableName)
return operatedb
@time_cost
@opendb2
#@time_cost
def any_function(any_parameter):
print(any_parameter)
any_function()
any_function(578)
可以看到,当装饰器增多时,可能的摆放组合是阶乘式增长的(运行结果也极其烧脑),而且一旦有异常处理,调试定位也极其麻烦!