Insert Into Array Problem

Asked

Viewed 256 times

2

Good, I’m trying to learn python because it seems to me a language with some applicability interest in the most diverse areas (and interest me for Raspberry).

As I learn I like to develop something to apply the knowledge.

As such I am developing a system consisting of a dictionary of classes (Created Class) whose identifier of each class is the acronym received.

Each class consists of an array of students (Created Class) and an acronym that identifies it.

All classes have setters and getters for all attributes.

My problem is that whenever I add a new student to a class already created and inserted in the class array, it adds it to all classes contained in the array and I can’t find the focus of the problem.

The code of my class class is as follows::

class Turma:
   nome = None
   sigla = None
   alunos = []
   def __init__(self, _nome, _sigla):
       self.nome = _nome
       self.sigla = _sigla
   def getNome(self):
       return self.nome
   def addAluno(self, _aluno):
       self.alunos.append(_aluno)
   def getSigla(self):
       return self.sigla
   def getAlunos(self):
       return self.alunos

The code of my student class is as follows::

class Aluno:
   nome = None
   idade = None
   numero = None
   def __init__(self, _nome, _idade, _num):
       self.nome = _nome
       self.idade = _idade
       self.numero = _num
   def getNome(self):
       return self.nome
   def getNumero(self):
       return self.numero
   def getIdade(self):
       return self.idade
   def setNome(self, _nome):
       self.nome = _nome
   def setIdade(self, _idade):
       self.idade = _idade
   def setNome(self, _num):
       self.numero = _num

In my system control file I have the following features:

turmas = {}
def createTurma():
   nome = input("Insira o nome da turma: ")
   sigla = input("Insira a sigla da turma: ")
   turmas[sigla] = Turma(nome, sigla)
   print(turmas);
   print("Turma Adicionada com Sucesso!")

def listTurma():
   sigla = input("Insira a sigla do curso: ")
   print(turmas[sigla].getNome())

def addAlunoTurma():
   num = 0
   nome = input("Insira o nome do aluno: ")
   idade = input("Insira a idade do aluno: ")
   sigla = input("Insira a sigla da turma: ")
   _aluno = Aluno(nome, idade, 0)
   turmas[sigla].addAluno(_aluno)

def getAlunosByTurma():
   sigla = input("Insira a sigla da turma: ")
   teste = turmas[sigla].getAlunos()
   print(len(teste))
   for i in turmas[sigla].getAlunos():
       print("Nome: " + i.getNome())
       print("Numero: " + str(i.getNumero()))
       print("--------------")

I detected this problem when the function getAlunosByTurma() because regardless of the acronym always prints all students.

Thank you!!

  • To know what is wrong there, it is necessary to see the code of the classes. The problem seems to be in the méotod getSigla . Over time, you’ll understand better Pythone seeing that explicit getters and setters are not needed in most cases - and when they are, they work implicitly - without having to be called as methods (properties).

  • Thank you for the answer! I already complemented a little more my doubt so that it is possible to have a better idea of the problem and changed the array for a dictionary, to be simpler to reach the class I want!

2 answers

0


Your problem is in this class class statement, along with a mistake common with anyone coming from Java to Python:

class Turma:
   nome = None
   sigla = None
   alunos = []
   def __init__(self, _nome, _sigla):
       self.nome = _nome
       self.sigla = _sigla

The "variable declaration" in the class body is incorrect and unnecessary in Python: this creates attributes of the class not for each instance as in Java.

As a rule, this is no problem because when you create a value for self.nome in the __init__, with self.nome = nome, an attribute is created in the instance of the object that "hides" the class attribute.

But in the case of alunos you create an empty list - and your methods do not create a new list - they only manipulate the list in self.alunos. No instance attribute being self.alunos, Python automatically accesses the attribute in self.__class__.alunos - which is a single list that is shared by all its instances of Turma.

Fixing this is pretty easy - simply change the beginning of your declaration Turma for:

class Turma: 
   def __init__(self, _nome, _sigla):
       self.nome = _nome
       self.sigla = _sigla
       self.alunos = []

Another tip: the literal object built with [] is a "list" (list), not an "array". You can use the word "list" even. And another: there is no need, d prefix local variables with "" - you must have read that if you agree that private attributes and methods are prefixed with "" - yes, the entnaot this is a convention - there is nothing magical in the language regarding variables that begin with _ (but there are for attributes that start with two __, care). Furthermore, you are prefixing local variables of the methods with "_" - these variables are internal to the methods, and are not visible "from outside" - there is no gain - nor conventional - in calling your parameter _idade and not of idade - but you lose in readability and ease of typing.

And, as I said above, in general you don’t need getters and setters: your program will work equally well if anyone who wants to change a student’s age does "student.age=12" instead of "student.setIdade(12)" - Because of GIL, these direct assignments are thread-safe. And if at some point you want to put a guard on the attributes (the system has grown and you want to avoid ages that are not positive integers larger than 5, for example) - then you write the getter and the Setter, but using "Property" Python - users of your class keep writing aluno.idade = 12 but this time the assignment will go through the Setter method.

0

I’m not sure how your classes are structured, but I have an idea of the program you’re doing. I made a small example that I think I can give you some light. Here, using dictionaries we can store relevant information to students and their classes

turmas = []

def createTurma():
   nome = input("Insira o nome da turma: ")
   sigla = input("Insira a sigla da turma: ")
   turmas.append({'nome': nome, 'sigla': sigla, 'alunos': []})

def addAlunoTurma():
   num = 0
   nome = input("Insira o nome do aluno: ")
   idade = input("Insira a idade do aluno: ")
   sigla = input("Insira a sigla da turma: ")
   if any(turma['sigla'] == sigla for turma in turmas): # verificamos se a sigla existe
        for turma in turmas:
            if sigla == turma['sigla']:
                turma['alunos'].append({'nome': nome, 'idade': idade})
                break
   else:
        print('turma não existe')

createTurma()
print(turmas)
addAlunoTurma()
print(turmas)
addAlunoTurma()
print(turmas)

By way of example, here we will add a class and two students, at the end we will have the classes in this format:

[{'nome': 'turma B1', 'sigla': 'B1', 'alunos': [{'nome': 'Miguel', 'idade': '30'}, {'nome': 'caoc10', 'idade': '25'}]}]

In which to access the data of the first class would:

turmas[0] # {'nome': 'turma B1', 'sigla': 'B1', 'alunos': [{'nome': 'Miguel', 'idade': '30'}, {'nome': 'caoc10', 'idade': '25'}]}
  • Your simpleemten answer removes all the Object Orientation from the application - it’s very hard to imagine that as a "fix". : -) Although, yes, if this is all the functionality of the program, dictionaries will work well.

  • Yes @jsbueno of course, as I said I don’t know how the classes are structured. I believe that you can easily implement something like this and solve the problem, the focus of the problem has nothing to do with Oop but with insertion in an array, which I assume is a list

  • Thank you for the answer! I already complemented a little more my doubt so that it is possible to have a better idea of the problem and changed the array for a dictionary, to be simpler to reach the class I want! The given solution works, however I would like to keep the focus on an OOP and understand what the problem is so that in the future do not make the same mistake!!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.