[SOLVED] How to print expression of a function defined in "def" statement

Issue

I’am using a small program calculating by dichotomy the root of a function (i.e. find x when f(x)=0). (I admit I stole this program from some SO post, but I can’t give the reference nor thank the author because I don’t remember where it was…)

The output I have is:

Root is: -0.567143
Delta with 0 is:  0.000000000166

I would like to also output the expression of the function I am working on, just as written in def f(x) so as to have:

Function is: x + np.exp(x)
Root is: -0.567143
Delta with 0 is:  0.000000000166

I wonder how to do that…? Can def f(x) be modified to store the function writing somewhere? Or is it necessary to do another type of manipulation elsewhere?

My program is:

def samesign(a, b):
        return a * b > 0

def dichotomy(func, low, high, tolerance=None):
    
    # func(low) and func(high) must have opposite signs
    assert not samesign(func(low), func(high)), ("\n"
                                                 "Assertion failed!\n"
                                                 "Replace low or high")
    condition = True

    while condition:
        midpoint = (low + high) / 2.0
        if samesign(func(low), func(midpoint)):
            low = midpoint
        else:
            high = midpoint
        if tolerance is not None and abs(high - low) < tolerance:
            break   
        condition = abs(high - low) > tolerance

    return midpoint

def f(x):
    # Define function
    return x + np.exp(x)

x = dichotomy(f, -1, 0, 1E-9)

import inspect
line_return = inspect.getsourcelines(f)[0][-1]
llr = len(line_return)
name = line_return[11 : llr-1]

print(f'Function is: {name}')
print(f'Root is: {x: .6f}')
print(f'Delta with 0 is: {f(x): .12f}')

Solution

As shown in How can I get the source code of a Python function?, you can get the full definition of the function with the inspect module.

>>> import inspect
>>> print(inspect.getsource(f))
def f(x):
    # Define function
    return x + np.exp(x)

Note that function f must be defined in a source file.

If you are only interested in the content of the return statement, you must explore the ast of the function to extract the return statement using of the ast module.

import ast


def get_return_statement(fct):
    root = ast.parse(inspect.getsource(f))
    try:
        return_node = next(
            node for node in ast.walk(root) if isinstance(node, ast.Return)
        )
        return ast.unparse(return_node.value)
    except StopIteration:
        return "None"

get_return_statement(f) will give you x + np.exp(x).

Edit for python prior to 3.9:

ast.unparse is only available since python 3.9. It can be replace by the astor third party library, by replacing ast.unparse with astor.to_source.

The result is slightly different with more parentheses: (x + np.exp(x)).

Answered By – Balaïtous

Answer Checked By – Marilyn (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.