Can't pass a list as class attribute
<p>I have created an iterator. I'm trying to iterate through recipe ingredients, to check if a vegan person can it it, or not.</p>

<pre><code>class Vegan:

    NONE_VEGAN_INGREDIENT = ['egg', 'milk', 'honey', 'butter']

    def __init__(self, *args):
        self.ingredient_list = (args)
        self.index = -1

    def __iter__(self):
        return self

    def __next__(self):
        if self.index == len(self.ingredient_list):
            raise StopIteration
        for ingredient in self.ingredient_list:
            if ingredient in Vegan.NONE_VEGAN_INGREDIENT:
                self.index += 1
                return ('{} is a vegan ingredient'.format(ingredient[self.index]))
            else:
                self.index += 1
                return ('{} is NOT a vegan ingredient'.format(ingredient[self.index]))

iterable = Vegan('tomato', 'banana', 'asd', 'egg', 'tomato')
iterator = iter(iterable)
while True:
    try:
        print(next(iterator))
    except StopIteration:
        break
</code></pre>

<p>as you can see, I'm passing *args, which should be a list, but whenever I try to run this, it iterates through the first word, and checks the letters of the word 'tomato'. I want my iterator to go through the ingredients, and if something is not in the NONE_VEGAN_INGREDIENT list, then print as it is in the code. How can I pass in a list?</p>

<p>Your issue is because you are indexing the ingredient not the tuple, <code>ingredient[self.index]</code> should be <code>self.ingredient_list[self.index]</code>. </p>

<p>You could  simplify your code to behave like yours but work by making <em>args</em> <em>iterable</em> so you can pass the strings as you were without needing to put them in a list etc..:</p>

<pre><code>class Vegan:
    NONE_VEGAN_INGREDIENT = ['egg', 'milk', 'honey', 'butter']

    def __init__(self, *args):
        self.ingredient_iter = iter(args)
    def __iter__(self):
        return self

    def __next__(self):
        ingredient = next(self.ingredient_iter)
        if ingredient in Vegan.NONE_VEGAN_INGREDIENT:
            return '{} is a vegan ingredient'.format(ingredient)
        return '{} is NOT a vegan ingredient'.format(ingredient)


iterable = Vegan('tomato', 'banana', 'asd', 'egg', 'tomato')

for ele in iterable:
    print(ele)
</code></pre>

<p>Output:</p>

<pre><code>In [2]: iterable = Vegan('tomato', 'banana', 'asd', 'egg', 'tomato')

In [3]: for ele in iterable:
   ...:         print(ele)
   ...:     
tomato is NOT a vegan ingredient
banana is NOT a vegan ingredient
asd is NOT a vegan ingredient
egg is a vegan ingredient
tomato is NOT a vegan ingredient
</code></pre>

<p>You raise a Stopiteration in your own code but calling <code>next(iterable)</code> will do the same so, the point of making an object iterable is you can iterate directly over it so no need for a try/except. Also <em>I'm passing args, which should be a list</em> is incorrect, args is a tuple.</p>

<p>Also if you have a lot of ingredients to check making <code>NONE_VEGAN_INGREDIENT</code> a set would be more efficient:</p>

<pre><code>NONE_VEGAN_INGREDIENT = {'egg', 'milk', 'honey', 'butter'}
</code></pre>

python oop