1

Im trying to iter on my dictionary useing this :

it = iter(db)
for i in it:
    print(i)

but when i run this what happens is an endless loop of printing the dictionary as a whole rather then on the keys of the dictionary

i use this as input :

ppl = Course(123, 'Principles of Programming Languages') 
os = Course(133, 'Operating Systems') 
db = DB()
db.setCourse(ppl, 'SE', 2, 1)
db.setCourse(os, 'SE', 3, 1) 

and my output is:

{123: ('Principles of Programming Languages', 'SE', 2, 1), 133: ('Operating Systems', 'SE', 3, 1)}
{123: ('Principles of Programming Languages', 'SE', 2, 1), 133: ('Operating Systems', 'SE', 3, 1)}
{123: ('Principles of Programming Languages', 'SE', 2, 1), 133: ('Operating Systems', 'SE', 3, 1)}

in a loop that never ends. im pretty sure that my next is messed up.

EDIT the DB code is long this is the iter part of it :

class DB()
    DataBase = {} 
    def __iter__(self):
        return iter(self.DataBase)
    def getCourse(self,cnum):
        for i in self.DataBase:
            if i == cnum:
                return self.DataBase[i]
    def getCoursesByDept(self,dept):
        for key, value in self.DataBase.items(): 
            if dept in value: 
                return self.DataBase[key]
    def getCoursesByDeptYear(self,dept,year):
        for key, value in self.DataBase.items():
            if dept in value and year in value:
                return self.DataBase[key]
    def getCoursesByDeptYearSem(self,dept,year,semester):
        for key, value in self.DataBase.items():
            if dept in value and year in value and semester in value:
                return self.DataBase[key]
    def setCourse(self,Course,dept,year,semester):
        self.DataBase[Course.cnum] = (Course.name,dept,year,semester)
    def removeCourse(self,cnum):
        for i in self.DataBase.keys():
            if i == cnum:
                del self.DataBase[i]

the correct output is :

Course 123: Principles of Programming Languages 
Course 133: Operating Systems 
Mike.G
  • 373
  • 2
  • 5
  • 11

1 Answers1

2

Looks like the easiest fix is:

class DB():
    ...
    def __iter__(self):
        return iter(self.DataBase)

and take out the __next__ method.

To create your own, you need to walk through the keys yourself in your __iter__:

    def __iter__(self):
        for key in self.Database:
            yield key

which creates a generator, and you still don't need a __next__; if you have to have a __next__, then you'll need to gather the keys, and then return them one by one.

Once you have return each and every key, you need to raise StopIteration everytime __next__ is called again -- meaning you can only iterate once -- better to stick with one of the above two options.

The reason you are currently getting an infinite loop is that everytime __next__ is called you return the entire dictionary -- no checks to see if you're done.

See this answer for a more thorough explanation of creating iterators.


If you want your DB class to look the same as a dict, then add keys(), items(), and values(); if you don't care or won't need those, then either the second option above, or create your own. The second option might look like:

    def __iter__(self):
        for key, value in self.Database.items():
            yield key, value

What happens here is that for every key, value pair in DB, both are return when iterating. So your original loop should look like:

it = iter(db)
for k, v in it:
    print('%s: %s' % (k, v))
Community
  • 1
  • 1
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237