3
\$\begingroup\$

I am looking for some way to improve my code. It works but it doesn't look good and I am almost sure that lot of Best Practices rules are violated.

The save_session() function, creates dictionary with other dictionaries nested in. At the end the dictionary is dump to .json file.

I will appreciate any suggestions and advice for improvement of this code.

For better understanding the code of save_session():

workouts_instances is the list of current WorkoutPlan instances,

WorkoutPlan stores instances of Training and Exercise,

Training stores instances of Exercise,

class WorkoutPlan:
 def __init__(self, name, trainings=list(), exercises=list()):
 self.name = name
 self.trainings = trainings
 self.exercises = exercises
 ...
class Training:
 def __init__(self, name, exercises=list()):
 self.name = name
 self.exercises = exercises
 ...
class Exercise:
 def __init__(self, name, details=dict()):
 self.name = name
 self.details = details
 ...

Here is the code of save_session():

def save_session():
 """Exports current data to .json file."""
 data_to_save = {}
 # add workout plans
 for workout in workouts_instances:
 data_to_save[workout.name] = {}
 # add trainings
 if workout.trainings:
 data_to_save[workout.name]["trainings"] = {}
 for training in workout.trainings:
 data_to_save[workout.name]["trainings"][training.name] = {}
 # add training exercises
 if training.exercises:
 data_to_save[workout.name]["trainings"][training.name]['exercises'] = {
 exercise.name: {} for exercise in training.exercises
 }
 for exercise in training.exercises:
 if exercise.details:
 data_to_save[workout.name]["trainings"][training.name]['exercises'][exercise.name][
 'details'] = {detail: value for detail, value in
 exercise.details.items()}
 # add exercises
 if workout.exercises:
 data_to_save[workout.name]["exercises"] = {}
 exercises_to_save = data_to_save[workout.name]["exercises"]
 for exercise in workout.exercises:
 exercises_to_save[exercise.name] = {}
 if exercise.details:
 details = exercise.details
 exercises_to_save[exercise.name]['details'] = {detail: value for detail, value in details.items()}
 with open(WORKOUTS_FILE, 'w') as json_file:
 json.dump(data_to_save, json_file, indent=4)

and here is the example of output, data stored in .json file:

{
 "FBV - Full Body Workout": {
 "trainings": {
 "Training A": {
 "exercises": {
 "squats": {
 "details": {
 "description": "squats with barbell",
 "series": 4,
 "repeats": 4,
 "load": 70
 }
 }
 }
 }
 },
 "exercises": {
 "some exercise name": {
 "details": {
 "description": "some description",
 "series": 5,
 "repeats": 5,
 "load": 60
 }
 },
 "bench press - wide": {
 "details": {
 "description": "bench press with wide grip",
 "series": 5,
 "repeats": 5,
 "load": 60
 }
 }
 }
 }
}
asked Jun 8, 2019 at 13:20
\$\endgroup\$
5
  • \$\begingroup\$ It would be better if you provide the code calling the function or example usage as well. \$\endgroup\$ Commented Jun 8, 2019 at 13:29
  • \$\begingroup\$ @pacmaninbw: save_session() is one of the menu options in console app. All it has to do is to write data into dictionaries and dump it to .json later. All I want to know is how to build this dictionary of nested dictionaries in more proper way than it is right now. \$\endgroup\$ Commented Jun 8, 2019 at 13:38
  • 1
    \$\begingroup\$ Right now the question is off-topic please see codereview.stackexchange.com/help/dont-ask and codereview.stackexchange.com/help/how-to-ask. By asking for examples of use I was trying to improve the question. \$\endgroup\$ Commented Jun 8, 2019 at 13:43
  • 2
    \$\begingroup\$ Simply put, if you add example input and output it means it's easier for people to understand the transformation that is happening - help us, help you. \$\endgroup\$ Commented Jun 8, 2019 at 13:51
  • \$\begingroup\$ I made some edits. Is it better now? \$\endgroup\$ Commented Jun 8, 2019 at 14:40

1 Answer 1

1
\$\begingroup\$

Some suggestions:

  • Do not use mutable default arguments, they will mess with your subsequent calls. There are some very rare cases where mutable default arguments make sense, but this does not look like one of those.
  • Split generation of data from saving that data to a file. That way either method can be reused. If you also pull out the file handle to a main method you can dependency inject the file handle and test the whole functionality.
  • details have the same pattern everywhere, so they should also be a class or should be part of Exercise.
  • Like most Python code this could benefit from type annotations using MyPy.
answered Jun 9, 2019 at 6:33
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.