Do python3 and PyQt5 handle class attribute memory in the same fashion?

Viewed 28

I have this code to edit dates that uses class atributes storing dates:

import datetime
from datetime import timedelta, date

class Tempus():
    def __init__(self):
        self.start_day = date.today() + timedelta(days = -7)
        self.end_day = date.today()

class Transform():
    def __init__(self,value):
        input_b = int(input("Enter number of days to add/substract: "))
        value.start_day = value.start_day + timedelta(input_b)
        print ("After Transform ",value,value.start_day)           # Memory_address_1

class Controller():
    def __init__(self):
        self.varA = Tempus()
        print ("Before change of date",self.varA,self.varA.start_day) # Memory_address_2
        Transform(self.varA)
        print ("After change of date",self.varA,self.varA.start_day)   # Memory_address_3

Controller()

This works as expected (with the object memory addresses being the same). When using pyqt5, I came with the following code:

import sys
import datetime
from datetime import timedelta, date
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QApplication, QWidget, QComboBox, QHBoxLayout, QVBoxLayout, QGridLayout, QMainWindow, QLabel, QDateTimeEdit

class Tempus():
    def __init__(self):
        self.start_day = date.today() + timedelta(days = -7)
        self.end_day = date.today()

class Duodate(QWidget):
    def __init__(self, parent):
        super().__init__(parent)

        hbox = QHBoxLayout()
        self.day_new = Tempus()
        print ("Duodate ",self.day_new,self.day_new.start_day,self.day_new.end_day) # Memory_address_1B
#- Label
        label = "Start date"
        labelA = QLabel(label)
        labelA.setFont(QFont('Verdana', 12))
        hbox.addWidget(labelA)
#- Combo DateEdit
        self.day = QDateTimeEdit(self.day_new.start_day)                 
        self.day.setFont(QFont('Verdana', 12))
        self.day.dateChanged.connect(self.on_date_changed)  
        hbox.addWidget(self.day)
        self.setLayout(hbox)

    def on_date_changed(self, newDate):
        conversion = newDate.toPyDate()
        print ("newDate ",newDate, conversion)
        self.day_new.start_day = conversion
        self.parent().things_have_changed()
        print (self.day_new)                         # Memory_address_2B

class Controller(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt5 - example")
        self.varA = Tempus()
        print (self.varA,self.varA.start_day) # Memory_address_3B

        layout = QVBoxLayout()
        self.widget = Duodate(self)
        layout.addWidget(self.widget)
        self.setLayout(layout)
        self.things_have_changed()

    def things_have_changed(self):
        print ("Things have changed ",self.varA,self.varA.start_day)    # Memory_address_4B

app = QApplication(sys.argv)
window = Controller()
window.show()
app.exec_()

This doesn't work as expected. The attempt to modify the class variable self.start_day never realizes as output by the function things_have_changed. This was puzzling but I noticed that in this case, memory addresses #1B and #2B are the same but different from #3B and #4B (that are the same). This was unexpected so I'm wondering if class Duodate made a copy of class Tempus (storing it at a different memory location) and if this behavior should be expected from classes built with pyqt5 components.

1 Answers

you have two Tempus instances in your code that don't share the instance member start_day.

for a python class, there are static members of the class and instance members, this code below should demonstrate the difference.

class foo:
    static_var = True

    def __init__(self):
        self.instance_member = True

a = foo()
b = foo()
a.instance_member = False
print(a.instance_member, b.instance_member) # False True 

foo.static_var = False
print(a.static_var , b.static_var ) # False False

general speaking anything defined inside the class, not inside a method of the class is a static member that belongs to the class, while anything defined inside a function is an instance member that only belongs to the instance (self), and can be different from one instance and the other, this behavior doesn't change between python and pyqt5 objects.

Related