TypeError: Class object is not iterable

Took the following code chunk from Corey Schafer. I note this is a common Python question and I’ve read a few threads like these, but have not found any relevant explanations.

class Employee:

    raise_amount = 1.04

    def __init__(self, first, last, pay):
        self.first = first
        self.last = last
        self.pay = pay
        self.email = first + '.' + last + '@company.com'

    def fullname(self):
        return '{} {}'.format(self.first, self.last)
    
    def apply_raise(self):
        self.pay = int(self.pay * self.raise_amount)

class Developer(Employee):
    
    raise_amount = 1.10

    def __init__(self, first, last, pay, prog_lang):
        super().__init__(first, last, pay)
        self.prog_lang = prog_lang

class Manager(Employee):

    def __init__(self, first, last, pay, employees = None):
        super().__init__(first, last, pay)
        if employees is None:
            self.employees = []
        else:
            self.employees = employees

    def add_emp(self, emp):
        if emp not in self.employees:
            self.employees.append(emp)
    
    def remove_emp(self, emp):
        if emp in self.employees:
            self.employees.remove(emp)

    def print_emps(self):
        for emp in self.employees:
            print('-->', emp.fullname())

dev_1 = Developer('Test', 'User', 50000, 'Python')
type(dev_1)
mgr_1 = Manager('Sue', 'Smith', 90000, dev_1)
mgr_1.print_emps()

gives the output:

>>> type(dev_1)
<class '__main__.Developer'>
>>> mgr_1 = Manager('Sue', 'Smith', 90000, dev_1)
>>> mgr_1.print_emps()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 15, in print_emps
TypeError: 'Developer' object is not iterable

However, when dev_1 is wrapped with brackets like so: mgr_1 = Manager('Sue', 'Smith', 90000, [dev_1]), the code works and returns this output:

>>> dev_1 = Developer('Test', 'User', 50000, 'Python')
>>> type(dev_1)
<class '__main__.Developer'>
>>> mgr_1 = Manager('Sue', 'Smith', 90000, [dev_1])
>>> mgr_1.print_emps()
--> Test User

My question: dev_1 is a class, but my understanding is that brackets are for lists. Why does wrapping a class object with [ ] work in this instance?

>Solution :

Because the object as the Traceback says is not iterable. If you wrap a class object with brackets [], you create a list of objects. And a list is an iterable.

When you call the print_emps() method, it goes through every single element in the self.employees list where every element is an object. Therefore when the emp.fullname() method is executed in the print statement, the name and surname of the Employee gets printed. But if you don’t put brackets, the iterator has nothing to iterate through.

A maybe more simplified example would be like this.

for i in 3:
   print(i)

This doesn’t print anything as 3 is just an integer and there is nothing to iterate through. BUT

for i in [3]:
   print(i)

This prints out 3 as you have created a list which is an iterable.

I hope this answers you question as this is one of the basics of Python. Don’t get discouraged while learning it, everyone had questions like this.

Have fun!

Leave a Reply