Python3. NameError: name '' is not defined

2

I am using PyQt5 with Python 3 and I am trying to import redis, but when making the connection it gives me this error

named 'connection' is not defined

the code I have it like this:

Logica:

import redis

Class Logica():

    conexion = redis.Redis()
    valores = None

    def Obtener_llaves(self):

        valores = conexion.key('*')

        for item in valores:
            return item

and the view:

Class Inicio(QWidget):

    programa = None

    def __init__(self, programa):

            self.prorama = programa
            super().__init__()

            self.ListaBD_txt = QTextEdit(self)
            self.ListaBD_txt.setText("")

            self.Btn_Calcular = QPushButton(self)
            self.Btn_Calcular.clicked.connect(self.mostrar_todo)

    def mostrar_todo(self):

        try:
            valor = self.programa.Obtener_llaves()
            self.ListaBD_txt.setText(valor)

        except Exception as inst:
            print(type(inst))
            print(inst)

the main:

import sys
from PyQt5.QtWidgets import QApplication
from logica import Logica
from redis-vista import Inicio

def main():

    app = QApplication(sys.argv)
    sh = Inicio(Logica())
    sh.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

and I already defined connection in the logic but I still get the same error and I do not know what it could be

    
asked by Angie Celeste 20.04.2018 в 16:36
source

1 answer

0

There are some errors in your code. These are errors, say "python" and not PyQt, so to illustrate and correct them I will dispense with redis or PyQt5 and everything else, and I will focus on the concepts.

Apart from the error of putting Class in upper case (I will assume that it was a mistake to copy it and I will ignore it), the problem is that you do things like this:

class MiClase():
    variable = "valor"

    def funcion(self):
        # Intento de usar la variable
        print(variable)

This simple example would already fail with the same problem that happens to you:

objeto = MiClase()
objeto.funcion()
  

NameError: name 'variable' is not defined

The reason is that the syntax for which you assign variables in the class declaration itself, for what it is used is to create "class attributes". That is, variable is an attribute of class MiClase .

Unlike other languages such as Java, you can not refer to a class attribute without putting the class in question in front of it. That is, when in funcion we try to access variable , python will not understand "automatically" that you are referring to MiClase.variable . You have to make it explicit:

class MiClase():
    variable = "valor"

    def funcion(self):
        # Intento de usar la variable
        print(MiClase.variable)

This will make the error disappear. But on the other hand, Did you want that ? That is, did you want variable to be a class attribute or were you trying to make it an object attribute instead?

Class attributes vs. Object attributes

The difference is that, when you instantiate that class for example like this:

objeto = MiClase()

The variable attribute does not belong to objeto , but to the class. Despite this, you can try to access that attribute through the object, for example these two lines will produce the same result:

print(objeto.variable)
print(MiClase.variable)

But this works because the first line, when trying to find the attribute variable in the objeto and not find it, python will next look for the class from which it was instantiated (and if not there either, in the class from which he inherits, etc.) until he finds it. That is why any of the two lines arrives at the same place.

Now , when you assign a new value to that attribute, you can fall into an error if you are not aware of what is happening. What do you think will happen if I change the value of MiClase.variable ? That is, what do you think the following code will print?

MiClase.variable = "Nuevo valor"
print(objeto.variable)
print(MiClase.variable)

If you answered that you will print in both cases "Nuevo valor" , you are correct. No surprises here. The assignment has changed the value of the class attribute, and therefore when we access it again, both through the class and through the object, we find the value changed.

And in this other case?

objeto.variable = "Sorpresa!"
print(objeto.variable)
print(MiClase.variable)

What will come out here? If you thought it would come out "Sorpresa!" twice, oh ... bad news. When you try to access an attribute of an object to change its value and that attribute does not exist in the object, a new one is created!

Now objeto does have an attribute variable , and it no longer uses the attribute of the class. The value "Sorpresa!" was stored in the new attribute of that object. The attribute of the class continues with its original value. We now have two attributes with the same name, one in the object, the other in the class.

This is often a source of problems, so in general the class attributes are not used much .

Instead, you always work with object attributes, and these are initialized in the __init__ constructor. Therefore, another implementation of the example would be:

class MiClase():
    def __init__(self):
        self.variable = "valor"

    def funcion(self):
        # Intento de usar la variable
        print(self.variable)

In this code self always refers to a specific instance of an object. So:

objeto = MiClase()

create a new object, call objeto.__init__() (passing it the object itself through self ) and in that function objeto.variable is created through the assignment self.variable="valor" . From there, in any other method of that object you can use self.variable .

Each new instance will have its own attribute variable . There will not be one of the same name in the class that can cause confusion

Something else

In your code you also had this strange loop:

    for item in valores:
        return item

If your intention was that in each iteration of the loop a value is returned, that is not what will happen, since obviously, once you make the first return you abandon the function and the loop will no longer be executed.

To do something similar to what you want, you should use yield instead of return , but this will convert that method into a generator , which is surely a matter for another question so that I do not extend more.

    
answered by 20.04.2018 в 19:32