Generator expression in class not producing output I expect

class, generator, python, python-3.x

Solution

While the other answers have correctly diagnosed the error (that your `evens` generator is being initialized with the original empty `data` list), I think the suggestion to set a value for `data` still won't do what you want.

Currently you can only iterate over `evens` once, and after you do it will have been consumed. What I think you want is for `evens` to always be accessible as a generator of the even values of whatever the current `data` value has. The way to do that is to make it a `property`, with a function that returns the generator each time it is called:

class Test:
    def __init__(self):
        self.data = []

    @property
    def evens(self):
        return (i for i in self.data if i % 2 == 0)

Usage:

>>> t = Test()
>>> t.data = [1, 2, 3, 4, 5, 6]
>>> list(t.evens)
[2, 4, 6]
>>> list(t.evens) # works more than once
[2, 4, 5]
>>> t.data = [10, 15, 20, 25, 30]
>>> list(t.evens)
[10, 20, 30]

If you needed a more complicated generator, you could use `yield` in the function, rather than returning a generator object, but a generator expression works easily enough for getting even values.

Problem

I'd like to use some generator expressions as attributes for some expensive computation of data. If possible I would like to be able to do something like this: ``` class Test: def __init__(self): self.data = [] self.evens = (i for i in self.data if i % 2 == 0) def __main__(): t = Test() t.data = [1,2,3,4,5,6,7,8] for item in t.evens: print(item) if __name__ == '__main__': __main__() ``` I would liked to have seen this print out `2 4 6 8` but this gives no output. Have I made some sort of simple mistake here? Is what I am trying to do here possible or will I need to use `yield` to do this?

Original source