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.