问题描述
在编写 reference 时,我开始怀疑是否无法简化/合理化我的代码。这个想法是让装饰器集中读取和写入数据库
我有以下(简单的家庭级)问题:我保持状态 一个 JSON 文件中的程序,有几个函数可以使用 那个“数据库”。有些只需要加载数据库,有些需要加载它, 然后写回文件。
我想在这些函数上使用装饰器来集中 数据库的读写。下面是简化版 我的代码,有两个功能:一个只消耗数据库,另一个 另一个也修改它。此代码有效并返回 期望值
url = 'https://www.adidas.com/us/women-athletic_sneakers'
driver = webdriver.Chrome('D:/chromedriver')
driver.get(url)
time.sleep(3)
time.sleep(2)
w_shoes = driver.find_elements_by_class_name('grid-item___3rAkS')
for shoe in w_shoes:
title = shoe.find_elements_by_xpath('//*[@id="product-search-results"]/div[2]/div[3]/div[4]/div[1]/div/div/div[3]/div[2]/a')[0].text
print(title)
因此我有两个装饰器:
是否可以更改这些装饰器,以便一个进行读取,另一个进行 DB 的写入?用一个或两个来装饰函数?
我不清楚的一点是,在每个装饰器中,都有对函数的实际调用。如果我有两个装饰器,我假设我需要调用该函数两次(每个装饰器一个 - 我当然不想这样做)。或者有更好的方法吗?
解决方法
您可以将这些函数分解为两个仅完成一项工作的简单函数:
- 加载数据库
- 写入数据库
def load_db(func):
def wrapper():
print("loading DB")
db = 5
# the db was loaded and is now passed to the function actually making use of it
ret_db = func(db)
# Check if returns a DB,this is required if it is written
if ret_db:
return ret_db
return db
return wrapper
def write_db(func):
def wrapper():
db = func()
# now we write the DB to the disk
print(f"writing DB: {db}")
return wrapper
@load_db
def do_stuff_load_only(*db):
# a function that just consumes the DB,without changing it
print(f"initial DB is {db}")
@write_db
@load_db
def do_stuff_load_and_write(*db):
# a function that consumes and chnages the DB (which then needs to be updated on disk)
print(f"initial DB is {db}")
db = 10
print(f"changed DB to {db}")
# returning the new DB
return db
do_stuff_load_only()
do_stuff_load_and_write()
这会打印出与您相同的输出。
在这种情况下,我们可以根据需要使用两个装饰器或一个。这里有两点需要注意:
- 如果进行更改,则需要返回数据库,否则将返回原始未修改的数据库(请参阅
load_db
的包装器) - 您只需按以下顺序使用装饰器:
write_db
和load_db
,由于包装函数需要参数,因此切换顺序将不起作用。