Обновление вложенного словаря с несколькими ключами во втором словаре - PullRequest
0 голосов
/ 09 апреля 2020

Итак, предисловие: я довольно новичок в кодировании & python, поэтому, пожалуйста, прости меня, если ты смотришь на это и удивляешься, «о чем он думал?».

Я работаю над своим первым реальным проектом вне учебных пособий и пытаюсь создать планировщик тренировок, особенно 5/3/1. Какая из этих программ занимает 90% от вашего повторного максимума и предоставляет программу, основанную на различных процентах от этого значения.

То, над чем я сейчас работаю / над чем застрял, - это создание вложенного словаря для представления тренировок за месяц. Есть 4 тренировки в месяц, и каждая тренировка имеет 3 подхода. Каждый набор представляет собой процент от значения self.training_max. Все эти значения хранятся в списке self.weights.

В итоге я хотел бы получить словарь, который выглядит следующим образом: {'Week 1': {'Set 1': 60, 'Set 2': 69, 'Set 3': 78}, 'Week 2': {'Set 1': 'Set 1': 64, 'Set 2': 74, 'Set 3': 83}} et c.

Если вы запустите его, вы увидите, что я так близко, но что-то не так с тем, как у меня метод .create_workout() обновляет словарь. Я добавил операторы print, чтобы помочь мне отслеживать рекурсию, и правильные значения вызываются в правильное время, но когда они добавляются в словарь, они добавляются как каждое отдельное значение родительского словаря.

Итак, к концу все наборы на все четыре недели получают одинаковые значения, так как они переопределяются каждый раз, когда вызывается change_value().

Чего мне не хватает? Я также очень открыт для любых других отзывов о том, что вы видите, поскольку, как я уже сказал, я все еще новичок в этом.

import math 

class exercise:

def __init__(self, name, reps, weight, unit='kg', weeks=4, sets=3):
    self.name = name.title()
    self.reps = reps
    self.weight = weight
    self.one_rep = math.floor(self.weight * (1 + (self.reps / 30)))
    self.training_max = math.floor(self.one_rep * .90)
    self.unit = unit
    self.percentages = [.65, .75, .85, .70, .80, .90, .75, .85, .95, .40, .50, .60]
    self.weights = [round (percentage * self.training_max) for percentage in self.percentages]
    self.weeks_list = ['Week ' + str(week + 1) for week in range(weeks)]
    self.sets_dict = {"Set " + str(set + 1): 0 for set in range(sets)}
    self.workout_dict = {week: self.sets_dict for week in self.weeks_list}

def create_workout_2(self):
    def change_val(dictionary_this, i_this):
        for key, weight in zip(dictionary_this.keys(), self.weights[i_this: i_this + 3]):
            print (f'Key = {key}. Weight = {weight}')
            dictionary_this[key] = weight

        return dictionary_this
    i = -3
    for week in self.workout_dict.keys():
        i+= 3
        print (f'\nFor loop: This is {week}, i_this is {i}, weights are {self.weights[i : i + 3]}, they key being used is {week}')
        self.workout_dict[week] = change_val(self.workout_dict[week], i)
        print (f'The values for {week} are {self.workout_dict[week]}')

    return self.workout_dict

squat_workout = squat.create_workout_2()
print (f'\nsquat.weights = {squat.weights}')
print (f'\nFinal squat_workout output= {squat_workout}')

1 Ответ

0 голосов
/ 09 апреля 2020

Ваша проблема в том, что вы используете один и тот же self.sets_dict для каждой недели. Таким образом, при обновлении программы на разные недели изменения применяются к всем неделям. Вы должны убедиться, что у вас есть уникальный sets_dict в неделю.

Вместо того, чтобы повторно использовать один и тот же диктовку, делайте его копию каждую неделю. Чтобы сделать копию, вы можете либо импортировать модуль copy и использовать copy.copy (в некоторых случаях, но не это, но вместо этого следует использовать copy.deepcopy). Однако другой способ получить поверхностную копию (например, copy.copy) - передать структуру данных ее конструктору. При этом удаляется запрос на добавление import copy в ваш файл. Он менее общий, но когда это возможно, я нахожу его более понятным.

Таким образом, все, что вам нужно сделать, это изменить

        self.workout_dict = {week: self.sets_dict for week in self.weeks_list}

на

        self.workout_dict = {week: dict(self.sets_dict) for week in self.weeks_list}

и код будет работать так, как вы собираетесь. Я хотел бы добавить еще одну вещь, хотя. Не требуется объявлять все переменные, используемые в методе класса, как self... Только те переменные, которые необходимо запомнить между методами. В вашем случае нет необходимости использовать self.percentages, self.week_list, self.sets_dict. Было бы лучше просто использовать percentages, weeks_list, sets_dict без self. (может показаться, что sets_dict нужно сохранить, но (копии) он уже хранится в self.workout_dict, поэтому прямой доступ не требуется.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...