ekiely
ekiely

Reputation: 102

Iterate Over Instances of a Class in Python

I've created a class called Equipment, to which I can pass attributes describing the piece of equipment, the sensor type monitoring it, and the data pin that sensor is associated with, for a given instantiation. I then initialize four (arbitrary number) different instances of that class, pass them the attributes that are relevant, and create a list of the variables that represent those instances. From there, I defined a function, based on a for loop, whose job it is to iterate over those instances so that I can pull data from their associated sensors recursively using the contents of the given instance. However, when I go to implement this, I receive a TypeError saying that the Equipment object is not iterable.

To me, this does not make much sense, since I've created instances of the class, which, presumably should exist in memory somewhere and be referenceable using their variable name. Thus, I'm really asking Python to iterate over a list object that contains references to instances of a given class, which shouldn't require the class itself to be iterable. Rather, from my understanding, this should allow for a specific instance to be referenced, and its attributes retrieved.

What am I missing in my current understanding, and how can I start to approach the implementation that I have described/am aiming for?

Here are the relevant code snippets:

class Equipment:

    def __init__(self, equipmentType, sensor, pin):
        self.equipmentType = equipmentType
        self.sensor = sensor
        self.pin = pin       

dht11Sensor = Adafruit_DHT.DHT11

minus20 = Equipment("Minus 20 Freezer", dht11Sensor, 4)
minus80 = Equipment("Minus 80 Freezer", dht11Sensor, 4)
incubator24 = Equipment("24 Degree Incubator", dht11Sensor, 4)
incubator18 = Equipment("18 Degree Incubator", dht11Sensor, 4)

equipment = [minus20, minus80, incubator24, incubator18]

def recursiveCheck(equipmentList):

    for equipment in equipmentList:
        humidity, temperature = Adafruit_DHT.read(equipment.sensor, equipment.pin)

        if humidity is not None and temperature is not None:
            print(f"Your {equipment.equipmentType} is currently {temperature} degrees C and the humidity is {humidity}%")

        else:
            recursiveCheck(equipment)

    time.sleep(5)
    recursiveCheck(equipmentList)

recursiveCheck(equipment)

Upvotes: 0

Views: 492

Answers (1)

saeed foroughi
saeed foroughi

Reputation: 1718

your problem is that you are calling the method recursively and hence in the second round you call it with the object itself instead of the list!

in the for-loop this line:

recursiveCheck(equipment)

you are calling the function with one Equipment object and when it runs, it tries to do the for-loop on this object which is not your list! you probably wanted your code to be like this:

class Equipment:

    def __init__(self, equipmentType, sensor, pin):
        self.equipmentType = equipmentType
        self.sensor = sensor
        self.pin = pin       

dht11Sensor = Adafruit_DHT.DHT11

minus20 = Equipment("Minus 20 Freezer", dht11Sensor, 4)
minus80 = Equipment("Minus 80 Freezer", dht11Sensor, 4)
incubator24 = Equipment("24 Degree Incubator", dht11Sensor, 4)
incubator18 = Equipment("18 Degree Incubator", dht11Sensor, 4)

equipment = [minus20, minus80, incubator24, incubator18]

def recursiveCheck(equipmentList):

    for equipment in equipmentList:
        humidity, temperature = Adafruit_DHT.read(equipment.sensor, equipment.pin)

        if humidity is not None and temperature is not None:
            print(f"Your {equipment.equipmentType} is currently {temperature} degrees C and the humidity is {humidity}%")

        else:
            recursiveCheck(equipmentList)

    time.sleep(5)
    recursiveCheck(equipmentList)

recursiveCheck(equipment)

so to recap, the first time that your code runs, it runs ok and doesn't encounter any error (you could fact-check it with a simple print or a counter), the failure happens when your code goes to else statement in the for-loop because you are trying to pass an object instead of a list!

=== update:

so if you want to start the list from a given index when it fails you could do this:

class Equipment:

    def __init__(self, equipmentType, sensor, pin):
        self.equipmentType = equipmentType
        self.sensor = sensor
        self.pin = pin       

dht11Sensor = Adafruit_DHT.DHT11

minus20 = Equipment("Minus 20 Freezer", dht11Sensor, 4)
minus80 = Equipment("Minus 80 Freezer", dht11Sensor, 4)
incubator24 = Equipment("24 Degree Incubator", dht11Sensor, 4)
incubator18 = Equipment("18 Degree Incubator", dht11Sensor, 4)

equipment = [minus20, minus80, incubator24, incubator18]

def recursiveCheck(equipmentList, index=0):

    for i in in range(index, len(equipmentList)):
        equipment = equipmentList[i]
        humidity, temperature = Adafruit_DHT.read(equipment.sensor, equipment.pin)

        if humidity is not None and temperature is not None:
            print(f"Your {equipment.equipmentType} is currently {temperature} degrees C and the humidity is {humidity}%")

        else:
            recursiveCheck(equipmentList, i)
            return;

while True:
    recursiveCheck(equipment)
    time.sleep(5)

so I have made your function non-recursive because if I didn't do that it would have became a mess in runtime, and it might have gotten hard to follow where it is going!!

Upvotes: 1

Related Questions