Search code examples
pythonnumpyyield

yield, get rid of generator object, return one array instead of three


I have this code:

import numpy as np

class B():
    def __init__(self,a,b):
        self.a = a
        self.b = b

    def __repr__(self):
        return 'B({0},{1})'.format(self.a,self.b)

class test():

    def __init__(self,name,method, measures=None):
        self.name = name
        self.method = method
        self.measures = measures

    def __repr__(self):
        return 'test({0.name},{0.method},{1})'.format(self,self.measures)

    def A(self,thevalues,another):

            if self.method == 'S' and another != self.name: 
                yield self.S(thevalues)

            if self.method == 'V':
                yield self.V(thevalues)

    def S(self, thevalues):
        # Change thevalues and return the updated 
        thevalues = np.array(thevalues)
        new_values = thevalues + 3
        yield new_values

    def V(self,thevalues):
        yield thevalues
        #return np.array(thevalues)

class basic():

    def __init__(self, name, thelist):
        self.name = name
        self.thelist = thelist

    def startp(self):
        values = []
        for i in self.thelist:
            if i.name == self.name and i.method != 'S':
                # Just fill some values to server as input to `A`
                for j in range(4):
                    values.append(j)
            # The `A` function will determine which functions inside 
            # `test` it will call
            yield i.A(values,self.name)

Starting from the bottom, up :

I am calling the startp function in order to stat the process.

I am initializing and filling the values list when certain criteria are met (name and method) in order to pass it to the functions A and S.

Then, I use yield in order to start calling A function for every object in list.

The A function checks and runs theS or V functions when certain criteria are met.

Using this data:

b1 = np.array([B(1,2), B(3,4)])
b2 = np.array([B(5,6), B(7,8)])
b3 = np.array([B(9,10), B(11,12)])

alist = [ test('a','V',b1), test('b','S',b2), test('c','S',b3)]
obs = basic('a',alist).startp()
for i in obs:
   for j in i:
       print(j)

Inside V function, if I use return np.array(thevalues), I am receiving:

[0 1 2 3]
<generator object test.S at 0x7f74fc1c0b48>
[3 4 5 6]
<generator object test.S at 0x7f74fc1c0bf8>
[3 4 5 6]

If I use yield thevalues, I am receiving:

<generator object test.V at 0x7f74ec99d678>
<generator object test.S at 0x7f74fc1c0bf8>
[3 4 5 6]
<generator object test.S at 0x7f74ec99d678>
[3 4 5 6]

But if I use:

for i in obs:
    for j in i:
        #print(j)
        for k in j:
            print(k)

I can access the V generated values but the result is:

[0, 1, 2, 3]
[3 4 5 6]
3
4
5
6
[3 4 5 6]
3
4
5
6

What I want is , if it possible, to receive only one array with the results:

[ [0 1 2 3],
  [3 4 5 6],
  [3 4 5 6]
]

And I must keep the yield statements in startp ( basically one yield is fine, I just use 2 yield because I want to pass values to S function)


Solution

  • Finally , I used:

    def startp(self):
            values = []
            result = []
            for i in self.thelist:
                if i.name == self.name and i.method != 'S':
                    # Just fill some values to server as input to `A`
                     for j in range(4):
                        values.append(j)
    
                values = np.array(values)
                result.extend(i.A(values,self.name))
    
            result = np.array(result)
            return result
    

    and I am receiving:

    temp = []
    for i in obs:
        for j in i:
            temp.extend(j)
    
    temp = np.array(temp)
    print(temp.shape)
    
    (3,4)