Accessing variable from another class

I’m working on a Python application with pyQt5, more specific with QThread, QObject, QMainWindow.

I have a main class (QMainWindow) with 2 functions (I run the functions here because I need to use/call QLabels, QLineEdit.text (), etc.) The function called “initialDF” downloads a data frame from the web and “plays” with it, finally the function gets a variable called "Test " and a final dataframe called “Data”. The funtion called “bucleDF” turn “Data”.

I need to use "Test " as While validator in another class (QObject) that runs my QThread and i need to call “Data” in While-loop for “update” the validator calling “Test”.

class Worker (QObject):    
    finished = pyqtSignal()
    stage1 = pyqtSignal()
    stage2 = pyqtSignal()

    def __init__(self) -> None:
        super().__init__(parent=None)
        

    def bucleRelleno(self):

        self.stage1.emit()       

        while test <= '17:00':
 
                self.stage2.emit()            
                lasttime = pd.to_datetime(max(data.index))
                lasttime = lasttime + datetime.timedelta(minutes=60)
                nexttime = lasttime + datetime.timedelta(minutes=2)
                test = "{:d}:{:02d}".format(nexttime.hour, nexttime.minute)                   
                t.sleep(1)
        self.finished.emit()


class MainWindow (QMainWindow):  
    global data
    def __init__(self, parent=None):
        super(MainWindow, self).__init__()
        uic.loadUi('xxxx', self)     
        self.run.clicked.connect(self.runLongTask)          

    def runLongTask(self):
        self.thread = QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.bucleRelleno)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.worker.stage1.connect(self.initialDF)
        self.worker.stage2.connect(self.bucleDF)
        self.thread.start()

    def initialDF(self):
        data = pandas.DataFrame()
        lasttime = pd.to_datetime(max(data.index))
        lasttime = lasttime + datetime.timedelta(minutes=60)
        nexttime = lasttime + datetime.timedelta(minutes=2)
        test = "{:d}:{:02d}".format(nexttime.hour, nexttime.minute)        
        
        return data, test


    def bucleDF(self):
        data2 = pandas.DataFrame()
        data = pd.concat([data, data2])
        return data

Classes are used to create objects.
If you want to access an attribute of an object, you can adress it by objectName.attribute. Ofcourse you need to create such an object and pass it’s name into the function that uses it.

1 Like

Hi Jagaya, thank you for your reply!
I did the following things but had no luck:

  1. I tried to call the “Test” attribute (remember that this attribute is inside the “InitialDF” function inside the “MainWindow” class) from the “bucleRelleno” function in the “Worker” class and I got the following error: AttributeError: 'function' object has no attribute 'test'

  2. I tried to create an object in class “Worker” inside no function and I get the following error:
    AttributeError: type object 'MainWindow' has no attribute 'test'

Variables within functions only exist while the function is running and are locally bound to the function - meaning they cannot be accessed from the outside.

If you want to use it’s value, you have to write it into an attribut of the class (like self.test) and then can access it via objectname.test.

1 Like

Thanks Jagaya!
As I understand it, I cannot call the “Test” attribute of the “InitialDF” function of the “MainWindows” class because the “InitialDF” function is executing through a QThread and it is not executing locally in the “Worker” class . It’s that right?

An “attribute” is a value within an object (self.name) and only those can be called.
What you have within a function is a variable and those are locally bound to the function - meaning they do not exist outside of the function and can not be called from anywhere other than within the function. It has nothing to do with classes or anything.

def add5(num):
  five = 5
  return num + five
print(add5.five) # error: add5 has no attribute five

The variable “five” is created when the function is called and deleted when the function is finished. It can never be adressed. Locally bound also means, that even if you were to create a variable named “five” outside the function, the “five” within would be independant of it.
There are keywords to work around this. One is if you are in a class, you can use “self.five” to turn it into an attribute of the object and then it is locally bound to the object - but objects are never “finished” hence you can call it as long as you create the object first. Unless you actively delete the object, it persists, unlike the function.

1 Like