yield + generator in python in class

Question:

I am very new in Python and I wanna create a generator object that yields two lists for Fibonacci sequence. First list of number and second list of fibonacci.
The function define in the class. Before it I define fibonacci function as below:

def fib(self, _n,) -> int:
        if _n == 0:
            return 0
        if _n == 1:
            return 1
        return self.fib(_n-1) + self.fib(_n-2)

I need to define def fib_seq(self, _n): function with yield and use gen() together.

I did it:

def fib_seq(self, _n):
        """
        - input: n=4
        - output: generator object that produces:
            ([0, 1, 2, 3, 4],
             [0, 1, 1, 2, 3])
        """
        for i in range(_n):
            nlist = gen(i)
            flist = gen(self.fib(i))

        yield ([nlist], [flist])

but I got below error in test part:

Traceback (most recent call last):
  File --- line 161, in <module> # this part is in test section
    n, fib = next(gen)      # trigger generator
             ^^^^^^^^^
  File ---, line 53, in fib_seq # this part is my code
    nlist = gen(i)
            ^^^^^^
TypeError: 'generator' object is not callable
Asked By: Maryam Mohebbi

||

Answers:

I’m not sure what the gen function you are using is, but you don’t need to use it. You could do (removing self in this example to have standalone functions):

def fib(_n):
    if _n == 0:
        return 0
    if _n == 1:
        return 1
    return fib(_n-1) + fib(_n-2)

def fib_seq(n):
    for i in range(n + 1):
        nlist = list(range(i + 1))
        flist = [fib(j) for j in range(i + 1)]
    yield (nlist, flist)

# as fib_seq yields a generator you have to use it in, e.g., a for loop
for k in fib_seq(4):
    print(k)

([0, 1, 2, 3, 4], [0, 1, 1, 2, 3])

Note that the for loop in fib_seq is a bit superfluous as it stands. You could move the yield to within the loop, e.g.,

def fib_seq(n):
    for i in range(n + 1):
        nlist = list(range(i + 1))
        flist = [fib(j) for j in range(i + 1)]
        yield (nlist, flist)

which would give:

for k in fib_seq(4):
    print(k)

([0], [0])
([0, 1], [0, 1])
([0, 1, 2], [0, 1, 1])
([0, 1, 2, 3], [0, 1, 1, 2])
([0, 1, 2, 3, 4], [0, 1, 1, 2, 3])

or, if you only want one output, have:

def fib_seq(n):
    nlist = list(range(n + 1))
    flist = [fib(j) for j in range(n + 1)]
    yield (nlist, flist)

which would give:

for k in fib_seq(4):
    print(k)

([0, 1, 2, 3, 4], [0, 1, 1, 2, 3])
Answered By: Matt Pitkin
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.