Display information of a binary search tree python

2

In a class, I have a method where I call my binary tree module (do not pay attention to the name of the treeAVL) and I save the information that I take from the database:

    def ingresarArbol(self):
        arbol=ArbolAVL.ArbolBinarioBusqueda()
        comando="SELECT * FROM tipo_inversion;"
        conectar=Base_de_datos.BaseDeDatos()
        conectar.cursor.execute(comando)
        for dato1, self.dato2 in enumerate(conectar.cursor.fetchall()): 
            arbol.__setitem__(self.dato2[0], self.dato2)
            print(arbol.__getitem__(self.dato2[0]))
        print(arbol.__getitem__('758654'))

with setitem I pass as parameter the first data as a key (which is the id) and all the other information, I put a print to see how each data is:

and it looks good, I also have another print ending the cycle where with getitem and as parameter one of the keys, it shows the data. up here everything is fine, but I have another method in the same class where I do the same, I send it to call the tree and with the same print, it shows me a None:

    def ArbolBusqueda(self):
        arbol=ArbolAVL.ArbolBinarioBusqueda()
        if self.palabra.get() not in self.id.get():
            self.listbox.insert(0, "No existe registro con ese id")

        print(arbol.__getitem__('758654'))

That the data is not supposed to be already in the tree, or I'm wrong, I think I'm not really understanding how a search tree works. Either way, here is part of the tree code

this to add the data:

    def agregar(self,clave,valor):
        if self.raiz:
            self._agregar(clave,valor,self.raiz)
        else:
            self.raiz = NodoArbol(clave,valor)
        self.tamano = self.tamano + 1

    def _agregar(self,clave,valor,nodoActual):
        if clave < nodoActual.clave:
            if nodoActual.tieneHijoIzquierdo():
                self._agregar(clave,valor,nodoActual.hijoIzquierdo)
            else:
                nodoActual.hijoIzquierdo = NodoArbol(clave,valor,padre=nodoActual)
        else:
            if nodoActual.tieneHijoDerecho():
                self._agregar(clave,valor,nodoActual.hijoDerecho)
            else:
                nodoActual.hijoDerecho = NodoArbol(clave,valor,padre=nodoActual)

    def __setitem__(self,c,v): 
        self.agregar(c,v)

this to get the data:

    def obtener(self,clave):
        if self.raiz:
            res = self._obtener(clave,self.raiz)
            if res:
                return res.cargaUtil
            else:
                return None
        else:
            return None

    def _obtener(self,clave,nodoActual):
        if not nodoActual:
            return None
        elif nodoActual.clave == clave:
            return nodoActual
        elif clave < nodoActual.clave:
            return self._obtener(clave,nodoActual.hijoIzquierdo)
        else:
            return self._obtener(clave,nodoActual.hijoDerecho)

    def __getitem__(self,clave):
        return self.obtener(clave)

and of course, the node class with its attributes and its functions. and the arbolbinario class looks for ()

here the whole class:

from tkinter import *
import psycopg2
import sys
import pprint
import Base_de_datos
import MergeSort
import ArbolAVL

class Tipo_inversion:
    def __init__(self,id=None,nombre=None,porcentaje_utilidad=None,tasa_pago=None):
            self.id=id
            self.nombre = nombre
            self.porcentaje_utilidad = porcentaje_utilidad
            self.tasa_pago =tasa_pago
    def ingresar(self):
        self.ventanaIngresar=Toplevel()
        self.ventanaIngresar.geometry("570x400")
        self.ventanaIngresar.title("Tipo de inversion")
        Label(self.ventanaIngresar, text="Tipo de inversion",font=("Cambria",14)).place(x=5,y=0)
        Label(self.ventanaIngresar, text="Id: ",font=("Cambria",11)).place(x=0,y=30)
        Label(self.ventanaIngresar, text="Nombre: ",font=("Cambria",11)).place(x=0,y=60)
        Label(self.ventanaIngresar, text="Porcentaje de utilidad: ",font=("Cambria",11)).place(x=0,y=90)
        Label(self.ventanaIngresar, text="tasa de pago: ",font=("Cambria",11)).place(x=0,y=120)

        self.id=StringVar()
        Entry(self.ventanaIngresar, textvariable=self.id).place(x=30,y=30)
        self.nombre=StringVar()
        Entry(self.ventanaIngresar, textvariable=self.nombre).place(x=65,y=60)
        self.porcentaje_utilidad=StringVar()
        Entry(self.ventanaIngresar, textvariable=self.porcentaje_utilidad).place(x=150,y=90)
        self.tasa_pago=StringVar()
        Entry(self.ventanaIngresar, textvariable=self.tasa_pago).place(x=90,y=120)

        Button(self.ventanaIngresar,text="Guardar",font=("Cambria",11),
                width=15,command=self.BD).place(x=420,y=5)

        Button(self.ventanaIngresar,text="Modificar",font=("Cambria",11),
                width=15).place(x=420,y=365)

        Button(self.ventanaIngresar,text="Mostrar",font=("Cambria",11),
                    width=15).place(x=0,y=365)

        Button(self.ventanaIngresar,text="Ordenar",font=("Cambria",11),
                    width=15).place(x=140,y=365)

        Button(self.ventanaIngresar,text="Buscar",font=("Cambria",11),
                    width=15,command=self.Busqueda).place(x=280,y=365)

        self.ventanaIngresar.mainloop()

    def BD(self):
        conectar=Base_de_datos.BaseDeDatos()
        comando="INSERT INTO tipo_inversion(id,nombre,porcentaje_utilidad,tasa_pago) VALUES('"+self.id.get()+"','"+self.nombre.get()+"','"+self.porcentaje_utilidad.get()+"','"+self.tasa_pago.get()+"')"
        print(comando)
        conectar.cursor.execute(comando)
    def Mostrar(self):
        print("hola")
    def Modificar(self):
        print("Hola")
    def Busqueda(self):
        self.ingresarArbol()
        self.palabra=None
        self.ventanaBusqueda=Toplevel()
        self.ventanaBusqueda.geometry("265x168")
        self.ventanaBusqueda.title("Buscar")
        Label(self.ventanaBusqueda, text="Ingresa el id del tipo de inversion",font=("Calibri Light",14)).place(x=5,y=0)
        self.palabra=StringVar()
        Entry(self.ventanaBusqueda, textvariable=self.palabra).place(x=70,y=30)
        Button(self.ventanaBusqueda,text="Buscar",font=("Cambria",11),
                width=10,command=self.ArbolBusqueda).place(x=90,y=60)
        self.listbox=Listbox(self.ventanaBusqueda, font=("Cambria",11), borderwidth=0, height=4,relief="sunken",width=30)
        self.listbox.place(x=7, y=95)

    def Buscar(self):
        comando="SELECT * FROM tipo_inversion where id='"+self.palabra.get()+"';"
        conectar=Base_de_datos.BaseDeDatos()
        conectar.cursor.execute(comando)
        if self.palabra.get() not in self.id.get():
            self.listbox.insert(0, "No existe registro con ese id")
        for dato1, dato2 in enumerate(conectar.cursor.fetchall()):
            self.listbox.insert(0, "Id: {}".format(dato2[0]))
            self.listbox.insert(1, "Nombre: {}".format(dato2[1]))
            self.listbox.insert(2, "porcentaje de utilidad: {}".format(dato2[2]))
            self.listbox.insert(3, "tasa de pago: {}".format(dato2[3]))

    def ingresarArbol(self):
        self.dato2=None
        arbol=ArbolAVL.ArbolBinarioBusqueda()
        comando="SELECT * FROM tipo_inversion;"
        conectar=Base_de_datos.BaseDeDatos()
        conectar.cursor.execute(comando)
        for dato1, self.dato2 in enumerate(conectar.cursor.fetchall()):
            #arbol[i]="{}".format(dato2)
            arbol.__setitem__(self.dato2[0], self.dato2)
            print(arbol.__getitem__(self.dato2[0]))
        print(arbol.__getitem__('758654'))

    def ArbolBusqueda(self):
        arbol=ArbolAVL.ArbolBinarioBusqueda()
        if self.palabra.get() not in self.id.get():
            self.listbox.insert(0, "No existe registro con ese id")

        print(arbol.__getitem__('758654'))
    
asked by Gonzo30 06.03.2018 в 04:33
source

1 answer

2

Without having thoroughly reviewed the code, because it is complex and uses import to include external classes whose code we can not see, I can see some details:

The class ArbolAVL.ArbolBinario , whose code we can not see complete but for what little we see I suspect that it is the same one that can be found aqui , provides methods such as __setitem__() and __getitem__() .

These methods are not intended to be invoked directly as you do in your code. They are the way in which we can implement in an own type an access syntax equal to the one that Python uses for lists and dictionaries. Thus, when python finds loquesea[indice] = valor , it checks if the loquesea object implements the __setitem__() method, and in that case calls loquesea.__setitem__(indice, valor) . Similarly, if loquesea[indice] appears as part of an expression, then it will invoke loquesea.__getitem__(indice) to get the value.

Although you can call those methods directly, the code is more readable if you use the syntax of the brackets. Most methods that have this __forma__ are for a similar role (we could say that they are for "internal use" of python and not for the user to use them explicitly). Another example, when you make x+y and x is of a type defined by the user, Python will try to invoke the x.__add__(y) method if that method exists. Again it is a matter of readability. What do you prefer suma = x.__add__(y) or suma = x+y ?

But the above is not an error in itself, it's just syntactic sugar to help read the program. What is surely an error is the way you create different trees by the code.

Every time you call ArbolAVL.ArbolbinarioBusqueda() you are creating a new tree. So for example, here:

class Tipo_inversion:
    # ...
    def ingresarArbol(self):
        self.dato2=None 
        arbol=ArbolAVL.ArbolBinarioBusqueda()
        # ...

you create a tree and assign it to the local variable arbol . This variable only exists while that method is running. Once the method has finished and returns, the variable is destroyed. The tree pointed to by that variable is removed from memory shortly afterwards by the garbage collector of python (which is a part of the interpreter that deals with freeing up memory occupied by data that is no longer being referenced by any variable). / p>

Later in another function:

class Tipo_inversion:
    # ...
    def ArbolBusqueda(self):
        arbol=ArbolAVL.ArbolBinarioBusqueda()

You create a new tree (you call the constructor ArbolAVL.ArbolBinarioBusqueda() again) and assign it to another variable arbol , which is not the same as before because the previous one disappeared because it was local. This new tree is empty, so it is not uncommon to not print anything when searching for a key. Moreover, this variable is also local and will also cease to exist once this method returns.

It seems that what you want therefore is to be able to access the same tree from both functions. A typical technique is to store that tree in an attribute of the object, rather than in a local variable. That is, in both functions changes arbol by self.arbol .

Additional details . You do not use the python conventions ( PEP 8 ) in your names. You have methods whose name starts with a capital letter (like Mostrar() , Modificar() , etc.) and the upper case is used only in class names. They should go in lowercase and using _ to separate words.

I see that you use self. in many parts of the code to assign values to things that I am not sure should be attributes of the object (for example self.listbox , self.dato2 , etc.) Attributes are created when they are assigned For the first time and in your code that happens in different functions so it is difficult to see at a glance which are all the attributes used by your class. It is usual to initialize all the attributes in the constructor (even with empty values or None ) to at least have them all together in view in one place. The attributes of the object are like "variables" assigned to the object itself and are used when it is necessary to access them from different methods of the object (as happened with the aforementioned arbol ). I do not see clearly that this is the case for many of your uses of self . Check it and change it to local variables (remove self ) if you do not need to share them between methods. The code will be cleaner.

    
answered by 07.03.2018 / 09:45
source