Почему этот словарь генерирует именно так?

#python #list #dictionary #generator

Вопрос:

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

 def scheduleMaker(dicty):
    weeks_to_sched = int(input("How many weeks?"))
    #weeks count
    weeks_count = [list(range(1, (weeks_to_sched   1)))]
    schedule = {}
    #for every week of the season
    for x in weeks_count:
        #add a entry in the dict for this week
        schedule[f"Week {x}"] = {}
        #every team that week needs a matchup
        for j in names:
            #this team needs to be added to week 1 with a matchup
            schedule[f"Week {x}"][j] = [j]
    print(schedule)

scheduleMaker(teams)
 

Я хочу, чтобы создавался словарь для каждой недели, а затем ключ: значения (совпадения) в словаре каждой недели. У меня возникли проблемы с первыми строками кода. Я получаю:

 {'Week [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]': {}
 

Вместо:

 {'Week 1': {}, 'Week 2': {}, 'Week 3: {}', etc}
 

Ответ №1:

Проблема в том, что здесь:

 weeks_count = [list(range(1, (weeks_to_sched   1)))]
 

Он создает список внутри списка, поэтому при повторении у weeks_count вас будет только один элемент (один элемент из всего диапазона).

Вместо этого измените его на:

 weeks_count = list(range(1, (weeks_to_sched   1)))
 

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

 weeks_count = range(1, (weeks_to_sched   1))
 

Ответ №2:

Прежде всего, вам нужно научиться отлаживать свой код и находить ошибки. Добавление простых строк печати поможет вам выявить проблемы

 print(weeks_count)
print(x)

#produces 
[[1, 2, 3]]
[1, 2, 3]
 

Это означает, что x это равно всему массиву вместо ожидаемого int. Это связано с тем, что вы добавили дополнительные скобки в список и сделали его массивом со списком в качестве 1-го элемента массива

     # not ok
    weeks_count = [list(range(1, (weeks_to_sched   1)))]
    # ok
    weeks_count = list(range(1, (weeks_to_sched   1)))
    # best
    weeks_count = range(1, weeks_to_sched   1)
 

Но также вам не нужно вести список weeks_count, так как вы можете выполнять итерацию непосредственно по диапазону (код ниже)

Я бы также рекомендовал не пропускать ввод, некоторую глобальную names переменную и логику создания расписания в 1 функцию. Лучший способ-передать все необходимые аргументы в эту функцию, чтобы она несла одну ответственность

окончательный код и выходные данные:

 def scheduleMaker(weeks_to_sched, names):
    schedule = {}
    for weekNum in range(1, weeks_to_sched   1):
        schedule[f"Week {weekNum}"] = {}
        for j in names:
            schedule[f"Week {weekNum}"][j] = [j]
    print(schedule)

weeks_to_sched = int(input("How many weeks?"))
scheduleMaker(weeks_to_sched, ['a', 'b', 'c'])

{'Week 1': {'a': ['a'], 'b': ['b'], 'c': ['c']}, 'Week 2': {'a': ['a'], 'b': ['b'], 'c': ['c']}, 'Week 3': {'a': ['a'], 'b': ['b'], 'c': ['c']}}
 

Ответ №3:

Вам нужно использовать range() функцию, чтобы иметь возможность выполнять цикл так, как вы описали.

Попробуйте сделать это вместо этого

 def scheduleMaker():
    weeks_to_sched = int(input("How many weeks?"))
    schedule = {}
    #for every week of the season
    for x in range(1, weeks_to_sched   1):
        #add a entry in the dict for this week
        schedule[f"Week {x}"] = {}
        #every team that week needs a matchup
        for j in names:
            #this team needs to be added to week 1 with a matchup
            schedule[f"Week {x}"][j] = [j]
    print(schedule)
 

Комментарии:

1. По какой-то причине автор начал счетчик с 1 для названий недель, поэтому, вероятно, ему может потребоваться использовать range(1, weeks_to_sched 1)

2. Согласен, для ясности я добавлю эту правку. Спасибо! @Виталий Москалюк