Is there a way to write a Python script that creates and executes code?
Question: Is there a way in Python to create Python code inside the Python script and
then execute/test it?

My function has the following type of form (as an example)

    
    
    def f(n):
        if n<=3: return [0, 0, 6, 12][n]
        return 2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4)
    

But I want to be able to create these kinds of functions dynamically (or any
arbitrary function for that matter) and then test their outputs during runtime
(as opposed to copying/pasting this function into the script and then manually
testing it).

Not sure if this makes sense, please ask for elaboration if needed. I've
already looked into eval and exec but couldn't get them to work with entire
function definitions, just basic statements like 1+2, etc.


Answer: There are a number of ways to do this kind of thing.

If the function can be described without "stepping outside the language", you
can just define a local function and return it, as in Blender's answer. This
is usually what you want when you think you need to define new functions
(borrowing Blender's example):

    
    
    def make_func(a, b):
        def f(n):
            return n**a + b
        return f
    

Sometimes, you can do even better, and represent the functions as data. For
example, how do you create an arbitrary polynomial function? Well, you don't
have to; you can have a _generic_ polynomial function that takes a list of
coefficients and a value and evaluates it; then all you need to do is create
coefficient lists.

In fact, I think this is the one you want here. As you say:

> It may be return 2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4) one minute, or
> return f(n-1) + 3*f(n-2) another, or f(n-1)+f(n-2)+f(n-3)+f(n-4)+5*f(n-5)
> depending on what I need it to be.

This can definitely be represented as a list of coefficients:

    
    
    def make_recursive_func(coefficients, baseval):
        def f(n):
            if n < len(coefficients): return baseval[n]
            return sum(coefficient * f(n-i-1) for i, coefficient in enumerate(coefficients))
        return f
    

But it's probably even simpler to write a single
`eval_recursive_func(coefficients, baseval)`, if all you're ever going to do
with the returned function is call it immediately and then forget it.

Sometimes—rarely, but not never—you really do need to execute code on the fly.
As Himanshu says, `eval` and `exec` and friends are the way to do this. For
example:

    
    
    newcode = '''
    def f(n):
        if n<=3: return [0, 0, 6, 12][n]
        return 2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4)
    '''
    exec(newcode)
    

Now the `f` function has been defined, exactly as if you'd just done this:

    
    
    def f(n):
        if n<=3: return [0, 0, 6, 12][n]
        return 2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4)
    

It's a bit different in Py3 than Py2, and there are variations depending on
what context you want things executed in, or whether you just want it executed
or evaluated or compiled or treated like an import, etc. But this is the basic
idea.

If you can't think of why you'd want to write the first instead of the second,
then you don't need this.

And if you can't figure out how to generate the right string on the fly, you
shouldn't be doing this.

And, as Ignacio Vazquez-Abrams points out, if these functions can be built out
of user input, you need to do something to validate that they're safe, usually
by compiling iteratively and walking the AST.

Finally, even more rarely, you need to use the `new` module (and/or `inspect`)
to create a new function object on the fly out of bits of other function
objects (or even out of hand-crafted bytecode). But if you need to know how to
do that, you probably already know how.

