Ошибка выхода индекса списка за пределы диапазона при добавлении нового ключа словаря с повторяющимися номерами индексов в указанном списке

#python #list #dictionary #index-error

Вопрос:

Не буду вдаваться в подробности на заднем плане. Функция myquery запускает скрипт, который извлекается из моей рабочей базы данных. Все складывается в список. Оттуда предполагается выгрузить все в таблицу Google, по одной строке за раз. Отлично работало, когда мне приходилось беспокоиться только о двух переменных, и я мог использовать что-то двоичное, например словарь. Что ж, теперь у меня есть еще; 4 категории, каждая из которых должна быть на своей линии.

Мне просто нужно разделить список (rawskudata) на несколько меньших списков (компонент), назначенных словарю (skuandimages). Проблема в этой строке:

skuandimages[c_list] = [rawskudata[int(c_sku)], rawskudata[int(c_img_url)], rawskudata[int(c_name)], rawskudata[int(c_quantity)]]

и я получаю ошибку индекса: индекс списка выходит за пределы диапазона.

основываясь на том, что я смотрел на него буквально два часа подряд и делал каждый результат поиска Google для «ошибки индекса» фиолетовым, это ДОЛЖНО сработать. в списке, из которого он извлекается, есть номер индекса. я сверился со всевозможными печатными заявлениями. почему?. почему бы и нет. я хочу умереть

 mycursor = mydb.cursor()  skuandimages = {   }  myquery2 = #insert top secret query here  mycursor.execute(myquery2)  rawskudata = []  c_tag = 0  c_sku = 0 c_img_url = 1 c_name = 2 c_quantity = 3  print(mycursor)  for xy in mycursor:  for yx in range(2,6):  rawskudata.append(str(xy[yx]))  print(rawskudata)  for z in range(0,len(rawskudata)):  #skuandimages[str(x[2])   "-"   str(x[3])] = x[4]  c_list = "componant"   str(c_tag)  skuandimages[c_list] = [rawskudata[int(c_sku)], rawskudata[int(c_img_url)], rawskudata[int(c_name)], rawskudata[int(c_quantity)]]  #skuandimages[c_list] = [x for x]  c_sku = c_quantity   1  c_img_url = c_quantity   2  c_name = c_quantity   3  c_quantity = c_quantity   4  c_tag  = 1   

Печать(rawskudata) возвращает это (данные изменены для обеспечения конфиденциальности):

 ['222001-1', 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/64/Garden_strawberry_(Fragaria_×_ananassa)_single.jpg/440px-Garden_strawberry_(Fragaria_×_ananassa)_single.jpg', 'Strawberry', '1', '222014-1', 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/78/Ripe,_ripening,_and_green_blackberries.jpg/440px-Ripe,_ripening,_and_green_blackberries.jpg', 'Blackberry', '1', '222053-1', 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e3/Oranges_-_whole-halved-segment.jpg/440px-Oranges_-_whole-halved-segment.jpg', 'Oranges', '1', '222123-1', 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Autumn_Red_peaches.jpg/440px-Autumn_Red_peaches.jpg', 'Peaches', '1', '222203-1', 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Pears.jpg/440px-Pears.jpg', 'Pears', '1']  

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

1. Отладка может быть неприятной, и обычно, чем проще ошибка, тем больше времени требуется, чтобы ее обнаружить. Добро пожаловать в SO, кто — нибудь сможет помочь. В качестве первого шага — не могли бы вы включить вывод print(rawskudata) (утверждение перед for z in ... ) в свой вопрос

Ответ №1:

Вы получаете данные из rawskudata 4 одновременно, поэтому вы хотите зациклиться на 1/4 количества элементов в rawskudata

 for z in range(0, int(len(rawskudata)/4)):  

Но есть более простой способ сделать это. Вы можете заменить все, что происходит после строки mycursor.execute(myquery2) , на:

 for xy in mycursor:  skuandimages["componant"   str(c_tag)] = [xy[2], xy[3], xy[4], xy[5]]  c_tag = c_tag   1  

Отзывы

Ниже я написал несколько отзывов о написанном вами коде, которые, надеюсь, помогут вам в изучении Python.

Когда вы получаете данные

 for xy in mycursor:  for yx in range(2,6):  rawskudata.append(str(xy[yx]))  

Было бы лучше использовать имена переменных

 for row in mycursor:  for sku_item in range(2,6):  

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

Строка rawskudata.append(str(xy[yx])) преобразует данные в строку. Обычно лучше оставить данные как есть, пока они вам действительно не понадобятся в виде строки. Таким образом, если бы вы хотели сделать с ним что-то еще, например, сравнить количество продукта, у вас была бы возможность сделать это.

В строке for z in range(0,len(rawskudata)): вместо использования имени переменной z обычно используется i сокращение index , когда вы берете индекс каждого элемента в списке, подобном этому, или некоторые люди будут использовать имя переменной _ для переменных, которые вы на самом деле никогда не используете в коде. Хотя обычно это красный флаг, что вы закодировали что-то более громоздким способом, когда вместо этого используете шаблон for i in range(0, len(some_list)): for some_value in some_list: .

В таких словарях, как skuandimages у вас, есть ключи и значения. Переменную c_list можно было бы назвать c_key лучше, поскольку она является ключом словаря, а не списком.

Линия

 skuandimages[c_list] = [rawskudata[int(c_sku)], rawskudata[int(c_img_url)], rawskudata[int(c_name)], rawskudata[int(c_quantity)]]  

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

Линии

 c_sku = c_quantity   1 c_img_url = c_quantity   2 c_name = c_quantity   3 c_quantity = c_quantity   4  

Кажется странным, что вы основываете все на количестве. Я бы предпочел создать новую переменную, имеющую базовое значение для этой итерации, а затем вы можете добавить 1, 2, 3, 4, и т.д. к нему. Также чаще всего поля продукта получают до того, как вы добавляете их в skuandimages что-то вроде:

 product_start_index = 0 for _ in range(0, int(len(rawskudata)/4)):   sku = rawskudata[product_start_index   0]  img_url = rawskudata[product_start_index   1]  name = rawskudata[product_start_index   2]  quantity = rawskudata[product_start_index   3]   key = "component"   product_start_index  skuandimages[key] = [sku, img_url, name, quantity]   product_start_index  = 4  

Или, возвращаясь к этим 4 строкам, другой альтернативой было бы

 c_sku  = 4 c_img_url  = 4 c_name  = 4 c_quantity  = 4  

Добавляя 4 к этим переменным каждый раз, когда вы проходите цикл. ( c_sku = 4 сокращенно c_sku = c_sku 4 от ). И теперь нет необходимости основываться на цифрах c_quantity

Одно последнее улучшение. Существует менее известная функция range ; третий параметр, который позволяет нам считать на 4, а не на 1. Зная это, мы действительно можем все упростить

 for i in range(0, len(rawskudata), 4):   sku = rawskudata[i   0]  img_url = rawskudata[i   1]  name = rawskudata[i   2]  quantity = rawskudata[i   3]   skuandimages["component"   i] = [sku, img_url, name, quantity]  

Но, как я уже упоминал ранее, лучшим решением было бы создавать skuandimages с самого начала, а не rawskudata :

 for xy in mycursor:  skuandimages["componant"   str(c_tag)] = [xy[2], xy[3], xy[4], xy[5]]  c_tag = c_tag   1  

И если вы действительно хотите сделать вещи компактными, это можно переписать как

 for i, product_data in enumerate(mycursor):  skuandimages["componant "   str(i)] = product_data[2:]  

enumerate даст нам обоим количество, 1, 2, 3 и т. Д. i , Каждый раз , когда мы проходим цикл, Вместе с фактическими данными о продукте. product_data[2:] это сокращенный способ получения подсписка, начинающегося со второго пункта и заканчивающегося в конце списка.

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

1. Красивые. Ты-святой. Я был слишком глубоко погружен в свои мысли. Это прекрасно работает. Спасибо.