简体   繁体   中英

Understanding output from recursive function

I am trying to run the function obtainingparams recursively for 5 times. However, currently the output from my program is as follows, and I am actually unable to understand why the line 32323232 in the while loop at the end of the code is not being printed out after every set of MATRIX , PARAMS , VALUES output.

MATRIX [[ 1.          7.53869055  7.10409234 -0.2867544 ]
 [ 1.          7.53869055  7.10409234 -0.2867544 ]
 [ 1.          7.53869055  7.10409234 -0.2867544 ]
 ..., 
 [ 1.          0.43010753  0.43010753  0.09642396]]
PARAMS [  5.12077446   8.89859946 -10.26880411  -9.58965259]
VALUES [(0.5, 1.5, 206.59958540866882, array([  5.12077446,   8.89859946, -10.26880411,  -9.58965259]))]
MATRIX [[ 1.          3.14775472  2.54122406 -0.43709966]
 [ 1.          3.14775472  2.54122406 -0.43709966]
 [ 1.          3.14775472  2.54122406 -0.43709966]
 ...,
 [ 1.          0.25806447  0.25806428  0.07982733]]
PARAMS [ 4.90731466  4.41623398 -7.65250737 -6.01128351]
VALUES [(0.5, 1.5, 206.59958540866882, array([  5.12077446,   8.89859946, -10.26880411,  -9.58965259])), (0.7, 1.7, 206.46228694927203, array([ 4.90731466,  4.41623398, -7.65250737, -6.01128351]))]

And so on. df is a Dataframe.

values = []

def counted(fn):
    def wrapper(*args, **kwargs):
        wrapper.called+= 1
        return fn(*args, **kwargs)
    wrapper.called= 0
    wrapper.__name__= fn.__name__
    return wrapper


@counted   
def obtainingparams(self, df, tau_1, tau_2, residuals):
        global values
        no_of_bonds = df.shape[0]         
        yields = df['coupon'].values

        matrix_of_params = np.empty(shape=[1, 4])

        months_to_maturity_matrix = df.months_to_maturity.values

        count = 0
        for x, value in np.ndenumerate(months_to_maturity_matrix):
            if count < months_to_maturity_matrix.shape[0]:
                months_to_maturity_array = months_to_maturity_matrix[count]
                years_to_maturity_array = months_to_maturity_array/12
                newrow = [1, ((1-np.exp(-years_to_maturity_array/tau_1))/years_to_maturity_array/tau_1), ((1-np.exp(-years_to_maturity_array/tau_1))/years_to_maturity_array/tau_1)-np.exp(-years_to_maturity_array/tau_1), ((1-np.exp(-years_to_maturity_array/tau_2))/years_to_maturity_array/tau_2)-np.exp(-years_to_maturity_array/tau_2)] 
                count = count + 1
                matrix_of_params = np.vstack([matrix_of_params, newrow])

        matrix_of_params = np.delete(matrix_of_params, (0), axis=0)  
        print('MATRIX', matrix_of_params)

        params = np.linalg.lstsq(matrix_of_params,yields)[0] 
        print('PARAMS', params)
        residuals = np.sqrt(((yields - matrix_of_params.dot(params))**2).sum())  
        tau_1 = tau_1 + 0.2 
        tau_2 = tau_2 + 0.2

        values.append((tau_1, tau_2, residuals, params))
        print('VALUES', values)

        while self.obtainingparams(df, tau_1, tau_2, residuals).called < 5:
            print('32323232')
            self.obtainingparams(df, tau_1, tau_2, residuals)

Edit : Calling obtainingparams which is a function within the BondClass Class:

tau_1 = 0.3
tau_2 = 1.3
BOND_OBJECT = BondClass.GeneralBondClass(price, coupon, coupon_frequecy, face_value, monthstomaturity, issue_date) 
residuals = [0, 0, 0, 0, 0]
df1 = Exc.ExcelFileReader() #Read the Dataframe in from an Excel File
BOND_OBJECT.obtainingparams(df1, tau_1, tau_2, residuals)

The problem is that you never enter the while loop because in order to enter it you make the recursive call. So before the test on called can be evaluated you are already recursing. This code is not what you want:

while self.obtainingparams(df, tau_1, tau_2, residuals).called < 5:

It looks up called in the result of the function call rather than in the function itself. Just replace it with:

while self.obtainingparams.called < 5:

and you should be just about there.

while self.obtainingparams(df, tau_1, tau_2, residuals).called < 5:
    print('32323232')
    self.obtainingparams(df, tau_1, tau_2, residuals)

My first instinct is that the self.obtainingparams().called has to call self.obtainingparams() to get the .called property. In this way, you're calling the function recursively, but not able to pass into the while loop before the function is called, explaining the lack of output.

I would suggest that instead of using a contained variable to count recursion instances, use a variable in the enclosing scope that can be incremented on each call, and have the base case check this variable and return once it reaches the amount of recursion steps you want.

Example:

count = 0

def recurse():
    count += 1
    # Base case
    if count >= 5:
        return
    else:
        recurse()

Lastly, you need to have another look at what this line of code actually does:

self.obtainingparams(df, tau_1, tau_2, residuals).called

Your function obtainingparams doesn't actually return a value, but say it returned an int . This line would really be checking int.called , but int does not have an attribute named called . If you wanted to check the attribute of the function object, you would want to check self.obtainingparams.called , although in my opinion there are better ways to do what you're trying to do with this code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM