It is a subject on which you have seen very little information in Spanish and, although I know that this information exists in other languages, it seems that there is no consensus on how to proceed in these cases.
Creating a class instance manually is trivial and well documented, but what happens when you want to create tens or hundreds of them at once?
To document this example I have relied on a CSV file as the data source, although a MySQL or other type of database could be used. In this case I am working with the list of most popular youtubers as of today. The aim is to instantiate the Youtuber class and create 'n' objects that contain the data of each of them.
From this:
We go to this:
And finally we are left with the CSV which is this:
Username, Rank, Grade, Uploads, Subs, VideoViews
InfantiLandia, 1st, A+, 604, 6200598, 1670464213
Doggy Doggy Play Doh Cartoons, 2nd, A, 817, 9412116, 2907777208
Mikecrack, 3rd, A, 1119, 5474520, 1673283126
Funny Stop Motion videos, 4th, A, 1669, 5474293, 3245474807
Las Ratitas, 5th, A, 69, 5055219, 1105609473
VEGETTA777, 6th, A, 4646, 23370994, 9219285021
MikelTube, 7th, A, 546, 1759368, 1083350993
Mejores Juguetes, 8th, A, 1185, 8522816, 5520591071
Antena 3, 9th, A, 17797, 3679111, 4069343965
Willyrex, 10th, A, 4249, 11987094, 2745094454
DaniRep | +6 Vídeos Diarios De GTA…, 11th, A, 8075, 7652330, 3816892816
Pica - Pica Oficial, 12th, A, 144, 2524721, 2075300230
TheGrefg, 13th, A, 2122, 6900066, 1664491396
elrubiusOMG, 14th, A, 778, 30479075, 6802868265
WildBrain en Español, 15th, A, 975, 1135008, 389562451
Little Baby Bum en Español, 16th, A, 387, 6394223, 3862272020
Pocoyo, 17th, A-, 998, 5289731, 4281735020
Makiman131, 18th, A-, 2327, 8610363, 1969438160
Manucraft, 19th, A-, 3669, 3896799, 1294439199
TheWillyrex, 20th, A-, 5065, 14396647, 5006342830
DalasReview, 21st, A-, 756, 7902658, 1590795277
Bibon KidsTV, 22nd, A-, 485, 958899, 243581857
Cleo & Cuquín - Familia Telerín, 23rd, A-, 68, 2844719, 1207898041
Historias de Juguetes, 24th, A-, 595, 2195985, 942501452
TheChacal547, 25th, A-, 531, 1946846, 894423954
Adexe & Nau, 26th, A-, 123, 7361150, 2594144877
TiempodeSol, 27th, A-, 153, 1193472, 559811498
TOYS on the go!, 28th, A-, 768, 5002505, 3529201221
Pablo Alborán, 29th, A-, 140, 3281004, 2289520362
ElTrollino, 30th, A-, 1294, 3201308, 684603542
WhiteZunder, 31st, A-, 4129, 2879454, 863070151
AuronPlay, 32nd, A-, 337, 9573591, 1326842520
Got Talent España, 33rd, A-, 741, 1401777, 479678377
iTownGamePlay *Terror&Diversión*, 34th, A-, 4922, 10583351, 3332300098
Los juguetes de Arantxa, 35th, A-, 715, 1956684, 728476972
laSexta, 36th, A-, 12504, 929328, 1114063775
Sorpresas Divertidas, 37th, A-, 652, 1662332, 548316058
Nani Bebés, 38th, A-, 14, 112797, 22539966
LOLiTO FDEZ, 39th, A-, 762, 3715772, 347220338
Folagor03, 40th, A-, 5641, 3200102, 1386847376
Pinkfong! Canciones Infantiles, 41st, A-, 312, 980481, 382830321
Massi, 42nd, A-, 2270, 2952875, 860773000
Disney Junior España, 43rd, B+, 1424, 2366474, 1789631207
ElChurches, 44th, B+, 1567, 4602516, 1164374169
TikTak Draw, 45th, B+, 419, 3330126, 497092666
ToonToon Juegos, 46th, B+, 208, 1685632, 513653223
Telenovelas, 47th, B+, 9125, 279595, 342653783
BreakMan, 48th, B+, 182, 2289049, 340118860
xFaRgAnx YT, 49th, B+, 3687, 2570330, 623452670
Casi Bebes, 50th, B+, 101, 1270722, 415082181
And now the Python code:
import csv
class Youtuber:
def __init__(self, Username, Rank, Grade, Uploads, Subs, VideoViews):
self.Username = Username
self.Rank = Rank
self.Grade = Grade
self.Uploads = Uploads
self.Subs = Subs
self.VideoViews = VideoViews
def importar_csv():
with open (r'C:\Users\usuario\Desktop\Tuberos.csv') as mi_archivo:
dialecto = csv.Sniffer().sniff(mi_archivo.readline())
mi_archivo.seek(0)
tuberías = csv.DictReader(mi_archivo, dialect=dialecto)
for i in range(0, len(list(tuberías))):
índice[i] = Youtuber(list(tuberías)[i]['Username'],list(tuberías)[i]['Rank'], list(tuberías)[i]['Grade'], list(tuberías)[i]['Uploads'], list(tuberías)[i]['Video Views'])
índice = {}
importar_csv()
print(índice.values)
...but I crash again and again against IndexError: list index out of range
.
Notice that if I do:
with open (r'C:\Users\usuario\Desktop\Tuberos.csv') as mi_archivo:
dialecto = csv.Sniffer().sniff(mi_archivo.readline())
mi_archivo.seek(0)
tuberías = csv.DictReader(mi_archivo, dialect=dialecto)
print(list(tuberías)[0]['Username'])
It returns the value correctly:
InfantiLandia
But as soon as I ask for 2 values or more:
with open (r'C:\Users\usuario\Desktop\Tuberos.csv') as mi_archivo:
dialecto = csv.Sniffer().sniff(mi_archivo.readline())
mi_archivo.seek(0)
tuberías = csv.DictReader(mi_archivo, dialect=dialecto)
print(list(tuberías)[0]['Username'])
print(list(tuberías)[0]['VideoViews'])
we return to
IndexError: list index out of range
.
I will read your ideas very carefully. Thanks.
csv.DictReader
returns an iterator that will return the rows of the csv one by one in the form of a dictionary where the key is the name of the column and the value is the content of the column for that row. Basically an iterator is "lazy", it only reads a new row from the file, parses it and returns it when we ask it, either by iterating over it or one by one by callingnext(iterador)
.Being an iterator, at the moment you
list(tuberías)[i]['Username']
iterate over it completely and "consume" it, so the followinglist(tuberías)[i]['Rank']
is an empty list , which causes an IndexError to be generated when trying to index .However , if you
list(tuberías)
iterate overtuberías
and create a dictionary list with all the rows in memory, with the contents of the entire file, this is really unnecessary and very inefficient. Even more so when instead of creating it once and iterating over it, you try to create it once for each column (6 lists per row).Simply iterate with an
for in
envelopetuberias
, since you need the index as the key for the instance dictionary you can useenumerate
:Since the names of the arguments ( keywords ) of the
__init__
match the keys of the dictionary (columns of the csv) you can pass the dictionary directly using**
.Instead of using a global variable that is modified by the function, it is a better practice to create the dictionary in the function and return it:
If the keys don't match the initializer arguments, just call passing the arguments positionally, getting each value from the dictionary by its key (column name in the csv):
or by keyword: