As I was writing another question, I started to wonder whether I could not simplify/rationalize my code. The idea is to have decorators that centralize the reading and writing of a database
I have the following (simple, home-grade) problem: I keep the state of a program in a JSON file and have several functions that make use of that "database". Some just need to load the DB, some need to load it, and then write back to file.
I wanted to use decorators on these functions to centralize the reading and writing of the database. Below is a simplified version of my code, with two functions: one that only consumes the DB, and another one that also modifies it. This code works and returns the expected values
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
func(db)
return wrapper
def load_and_write_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
# we will get back the changed database
db = func(db)
# 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}")
@load_and_write_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()
# Output:
#
# loading DB
# initial DB is (5,)
# loading DB
# initial DB is (5,)
# changed DB to 10
# writing DB: 10
I have therefore two decorators:
- one to read the DB, and pass it to the function
- another one to read the DB, pass it to the function, and retrieve the modified DB to write it back
Would it be possible to change these decorators so that one does the reading, and the other one the writing of the DB? And decorate function either with one or both?
The point that is not clear to me is that in each of the decorators, there is the actual call to the function. If I have two decorators I assume that I would need to call the function twice (one from each decorator - something that I of course do not want to do). Or is there a better approach?