0

I have a class Device which has two children: SmartSwitch and Refrigerator. My problem is that SmartSwitch has attributes that I assigned to Refrigerator, which shouldn't happen.

Here's how I'm printing out the output:

device_dict = {}
device_dict["Kitchen Fridge"] = Refrigerator("Kitchen Fridge", 2)
device_dict["Water Heater Switch"] = SmartSwitch("Water Heater Switch")
for device_name2 in device_dict:
    print("{}:\n{}\n-----\n".format(device_name2, device_dict[device_name2].get_data()))

Here's the output:

Kitchen Fridge:
{'Name': 'Water Heater Switch', 'State': 'off', 'temp': 2, 'Type': 'Smart Switch'}
-----

Water Heater Switch:
{'Name': 'Water Heater Switch', 'State': 'off', 'temp': 2, 'Type': 'Smart Switch'}
-----

Water Heater Switch is completely overriding Refrigerator's data.

Here's the code for the classes I'm using:

Device:

class Device:
    data = {"Name": None, "State": "off"}

    def __init__(self, name, state=None):
        self.data["Name"] = name
        if state is not None:
            self.data["State"] = state
        super().__init__()

    def get_data(self):
        return self.data

    def set_name(self, name):
        self.data["Name"] = name
        return self.get_data()

    def set_state(self, state):
        self.data["State"] = state
        return self.get_data()

SmartSwitch:

from Device import Device as Parent, Device
class SmartSwitch(Device):
    def __init__(self, name):
        super().__init__(name)
        self.data["Type"] = "Smart Switch"

Refrigerator:

from Device import Device


class Refrigerator(Device):
    def __init__(self, name, temp=None):
        super().__init__(name)
        if temp is not None:
            self.data["temp"] = temp
        self.data["Type"] = "Refrigerator"

    def set_temperature(self, temp):
        self.data["temp"] = int(temp)
        return self.get_data()
wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • 1
    Why is `data` seemingly treated as both an instance variable and a class variable? Why are you using getters and setters? – AMC Jan 29 '20 at 18:20

2 Answers2

0

The problem is that there's only one data dict, which is in Device's class scope. You could move data into the __init__ method, but really you should be using attributes in the first place. To get all the attribute-value pairs of an object, use its __dict__ special attribute.

As well, you don't need getters and setters in Python, and you don't need super().__init__() in a class that has no parents.

So the code should look like this:

class Device:
    def __init__(self, name, state="off"):
        self.name = name
        self.state = state

class SmartSwitch(Device):
    def __init__(self, name):
        super().__init__(name)
        self.type = "Smart Switch"

class Refrigerator(Device):
    def __init__(self, name, temperature=None):
        super().__init__(name)
        self.temperature = temperature
        self.type = "Refrigerator"

devices = {}
devices["Kitchen Fridge"] = Refrigerator("Kitchen Fridge", 2)
devices["Water Heater Switch"] = SmartSwitch("Water Heater Switch")
for device_name, device in devices.items():
    print(device_name)
    print(device.__dict__)

Output:

Kitchen Fridge
{'name': 'Kitchen Fridge', 'state': 'off', 'type': 'Refrigerator', 'temperature': 2}
Water Heater Switch
{'name': 'Water Heater Switch', 'state': 'off', 'type': 'Smart Switch'}

I also changed temp to temperature to avoid confusion with "temporary".

wjandrea
  • 28,235
  • 9
  • 60
  • 81
-1

So I fixed the issue by adding the dict instance data = {"Name": None, "State": "off"} to each of the children classes.

e.g.

class SmartSwitch(Device):
    data = {"Name": None, "State": "off"}
    def __init__(self, name):
        super().__init__(name)
        self.data["Type"] = "Smart Switch"
  • You didn't fix it, just moved the problem to the child classes. I'm writing you a proper solution now. – wjandrea Jan 29 '20 at 16:37