pythonpython-3.xintegrationnested-functionsimpsons-rule

Accessing the variable of a function within a function


So say I have the lower value and an upper value of an integral that's from the user input. I ask for the lower limit first then I check for its validity. Then in order to compare the value of my upper limit with my lower I made a nested function, so that I can also ask for user input of the upper limit, checks its validity and making sure that my upper limit is bigger than my lower(cuz u know integration), shown with the code below.

def LowLimCheck():
    while True:
        try:
            a = float(input("Please enter the lower limit of the integral: "))
            break
        except ValueError:
            print("Invalid input. Please enter a number.")
    print("You have chosen the lower limit: ", a)      

    def UppLimCheck():
        b = -1
        while b <= a:
            while True:
                try:
                    b = float(input("Please enter the upper limit of the integral: "))
                    break
                except ValueError:
                    print("Invalid input. Please enter a number.")

            if b <= a:
                print("The upper limit must be bigger than the lower limit!")
        print("You have chosen the upper limit: ", b) 
        return b           
    UppLimCheck()  
    return a

Now this is all well and fine until I actually need to use the values a and b because I need to put those values into an integral that I've set up. It's basically a general integral made by the Simpson's rule, that is trivial to get into right now. So I defined the function as:

def simpsonsRule(func, a, b, N):

    <insert code here>
    <insert code here>

    return d

OK so my function basically lets user insert any arbitrary function, the upper limit(a), the lower limit(b) and N(number of strips in Simpson's rule) and it spits out d which is the evaluation of the integral of the arbitrary function above by Simpson's Rule. My problem now is that when I'm trying to print the answer, I can take the variable a out and put in into the integral but I can't take the variable b out because it's in a function! For example if I now print the integrated value(say in this case of sin(x) and N = 20)

print(simpsonsRule(lambda x:np.sin(x), a, b, 20)

So I know that a and b values are local within their own functions. Now for the value of a I could easily just do this to get the value a

k = 0 #initialising the variable
k = LowLimCheck()
print(simpsonsRule(lambda x:np.sin(x), k, b, 20)

Because since k invokes LowLimCheck() which returns the value for a which I can put into my function. But how can I get my value of b which is nested within the first function? I want to use b basically. Is there a way round this?

Apologies for the lengthy question and thanks in advance!


Solution

  • You can return a tuple from LowLimCheck():

    def LowLimCheck():
        ...
        b = UppLimCheck() 
        return (a,b)
    

    then unpack them when calling LowLimCheck()

    a, b = LowLimCheck()
    

    UPDATE:

    In the most direct answer to your question, LowLimCheck() becomes:

    def LowLimCheck():
        while True:
           try:
                a = float(input("Please enter the lower limit of the integral: "))
                break
            except ValueError:
                print("Invalid input. Please enter a number.")
        print("You have chosen the lower limit: ", a)      
    
        def UppLimCheck():
            b = -1
            while b <= a:
                while True:
                    try:
                        b = float(input("Please enter the upper limit of the integral: "))
                        break
                    except ValueError:
                        print("Invalid input. Please enter a number.")
    
                if b <= a:
                    print("The upper limit must be bigger than the lower limit!")
            print("You have chosen the upper limit: ", b) 
            return b     
    
        b = UppLimCheck()   # Storing the b
        return (a,b)        # Passing b out with a in a tuple
    

    then call

    a, b = LowLimCheck()
    

    finally,

    print(simpsonsRule(lambda x:np.sin(x), a, b, 20)
    

    ALTERNATIVE SOLUTION (more substantial changes, but better code structure - as described in the original comments; flatter, more readable, fewer scope considerations):

    def LowLimCheck():
        while True:
            try:
                a = float(input("Please enter the lower limit of the integral: "))
                break
            except ValueError:
                print("Invalid input. Please enter a number.")
        print("You have chosen the lower limit: ", a)      
    
        return a
    
    def UppLimCheck(a):
        b = -1
        while b <= a:
            while True:
                try:
                    b = float(input("Please enter the upper limit of the integral: "))
                    break
                except ValueError:
                    print("Invalid input. Please enter a number.")
    
            if b <= a:
                print("The upper limit must be bigger than the lower limit!")
        print("You have chosen the upper limit: ", b) 
    
        return b  
    

    then:

    lowLim = LowLimCheck()
    upLim  = UppLimCheck(lowLim) # pass in lowLim as an argument
    
    print(simpsonsRule(lambda x:np.sin(x), lowLim, upLim, 20)