-2
from collections import defaultdict
from goody import type_as_str

class Bag:
    def __init__(self, i=None):
        self.bag = []
        if i == None:
            pass  # i is None, do nothing after create empty bag
        elif type(i)==list:
            self.bag.extend(i) # append whole list i into bag with extend method
        else:
            self.bag.append(i) # append single item i into bag 

    def __repr__(self):
        for s in self.bag :
            return s

    def __str__(self):
        for s in self.bag :
            return s

    def __len__ (self):
        if 'Bag()' in self.bag:
            return 0
        else:
            return len(self.bag)
    def unique(self):
        l = []
        if len(self.bag) == 0:
            return 0
        else:
            for x in self.bag:
                if x not in l:
                    l.append(x)
                else:
                    continue
            return len(l)

    def __contains__ (self,i):
        if i in self.bag:
            return True
        else:
            return False

    def count(self,i):
        return self.bag.count(i)

    def add(self,i):
        self.bag.append(i)

    def __add__(self,i):
        for x in i:
           self.bag.append(x)

    def remove(self,i):
        if i not in self.bag:
            raise ValueError
        for x in self.bag:
            if x == i:
                self.bag.remove(x)
                break


    def __eq__ (self,i):
        return self.bag == i 

    def __ne__ (self,i):
        return self.bag != i

    def __iter__(self):
        class PH_iter:
            def __init__(self,i):

                self.l = i

            def add(self,i):
                self.l.append(i)

            def remove(self,i):
                self.l.pop(i)

        return PH_iter(self.l)




if __name__ == '__main__':
#driver tests
import driver
driver.default_file_name = 'bsc1.txt'
#     driver.default_show_exception= True
#     driver.default_show_exception_message= True
#     driver.default_show_traceback= True
driver.driver()

Bag function generally returns a list. Writing Bag() constructs an empty bag. Writing Bag(['d','a','b','d','c','b','d']) construct a bag with one 'a', two 'b's, one 'c', and three 'd's.

The iter method is supposed to be defined in the bag class to add or remove item from the list.

The input is:

# Test iterator
e-->[i for i in sorted(b)]-->['a', 'b', 'b', 'c', 'd', 'd', 'd']
c-->i = iter(b)
c-->b.add('d')
c-->b.remove('a')
e-->[i for i in sorted(b)]-->['b', 'b', 'c', 'd', 'd', 'd', 'd']
e-->[i for i in sorted(x for x in i)]-->['a', 'b', 'b', 'c', 'd', 'd', 'd']

The error i got is:

 94 # Test iterator
 95 *Error: [i for i in sorted(b)] raised exception AttributeError: 'Bag' object has no attribute 'l'
 96 *Error: i = iter(b) raised exception AttributeError: 'Bag' object has no attribute 'l'
 99 *Error: [i for i in sorted(b)] raised exception AttributeError: 'Bag' object has no attribute 'l'
 100 *Error: [i for i in sorted(x for x in i)] raised exception NameError: name 'i' is not defined

Can anyone help me to fix the iter function to make it work? Many thanks.

weiyiwang
  • 1
  • 2
  • 4
    "The iter method is supposed to be defined in the bag class to add or remove item from the list." - that is not at all what `__iter__` methods are designed for. Are you sure you understand your assignment? – user2357112 Oct 23 '16 at 22:25
  • See [`object.__iter__` specification on python.org](https://docs.python.org/3/reference/datamodel.html#object.__iter__) – zvone Oct 23 '16 at 22:28
  • Are you using Python 2.x? If so: `class Bag(object):` – Hai Vu Oct 23 '16 at 22:30

1 Answers1

0

In __iter__, this line is causing the runtime error

return PH_iter(self.l)

It should be

return PH_iter(self.bag)

And this implementation is going to give you some surprise after iteration because it actually modified the data content of self.bag

You can improve it by

def __iter__(self):
    class PH_iter:
        def __init__(self,i):
            self.l = list(i)  # make a copy of the list i
Anthony Kong
  • 37,791
  • 46
  • 172
  • 304
  • I changed it and I get the following Error: – weiyiwang Oct 23 '16 at 22:29
  • *Error: [i for i in sorted(b)] raised exception TypeError: iter() returned non-iterator of type 'PH_iter' 96 *Error: i = iter(b) raised exception TypeError: iter() returned non-iterator of type 'PH_iter' 99 *Error: [i for i in sorted(b)] raised exception TypeError: iter() returned non-iterator of type 'PH_iter' 100 *Error: [i for i in sorted(x for x in i)] raised exception NameError: name 'i' is not defined – weiyiwang Oct 23 '16 at 22:30
  • Do you know what is "iter() returned non-iterator of type 'PH_iter'' supposed to mean? – weiyiwang Oct 23 '16 at 22:34
  • Python expects an iterator coming from `__iter__` method. An iterator is a class that support either `next` (p2) or `__next__` (p3). This SO entry should answer your question: http://stackoverflow.com/questions/9884132/what-exactly-are-pythons-iterator-iterable-and-iteration-protocols – Anthony Kong Oct 23 '16 at 22:36