83

How to dynamically create a function in Python?

I saw a few answers here but I couldn't find one which would describe the most general case.

Consider:

def a(x):
 return x + 1

How to create such function on-the-fly? Do I have to compile('...', 'name', 'exec') it? But what then? Creating a dummy function and replacing its code object for then one from the compile step?

Or should I use types.FunctionType? How?

I would like to customize everything: number of argument, their content, code in function body, the result, ...

asked Jul 2, 2012 at 9:47
5
  • 5
    possible duplicate of True dynamic and anonymous functions possible in Python? Commented Jul 2, 2012 at 10:02
  • I don't think it a duplicate: dynf = FunctionType(compile('def f(x): return x + 3', 'dyn.py', 'exec'), globals()) and print dynf(1) breaks with TypeError: '<module>() takes no arguments (1 given)' Commented Jul 2, 2012 at 10:06
  • 2
    Just because the answer there might be wrong doesn't mean this isn't a duplicate question. Commented Jul 2, 2012 at 10:10
  • The linked question has an updated answer demonstrating how to create a function with arguments. Commented Jul 2, 2012 at 14:32
  • are you sure you can't achieve what you want using functional programming as it exists in python (lambdas, closures, compositions...)? the code objects are fiddly, and they're not well documented (or really at all). Plus they're considered internals, subject to change with or without notice. Commented Jul 20, 2017 at 22:21

9 Answers 9

44

Use exec:

>>> exec("""def a(x):
... return x+1""")
>>> a(2)
3
answered Jul 2, 2012 at 10:25
Sign up to request clarification or add additional context in comments.

2 Comments

if anyone gets NameError consider using `locals().get('a')
given the option of safer alternatives, I think this answer should come with an appropriate warning
40

Did you see this, its an example which tells you how to use types.FunctionType

Example:

import types
def create_function(name, args):
 def y(): pass
 y_code = types.CodeType(args,
 y.func_code.co_nlocals,
 y.func_code.co_stacksize,
 y.func_code.co_flags,
 y.func_code.co_code,
 y.func_code.co_consts,
 y.func_code.co_names,
 y.func_code.co_varnames,
 y.func_code.co_filename,
 name,
 y.func_code.co_firstlineno,
 y.func_code.co_lnotab)
 return types.FunctionType(y_code, y.func_globals, name)
myfunc = create_function('myfunc', 3)
print repr(myfunc)
print myfunc.func_name
print myfunc.func_code.co_argcount
myfunc(1,2,3,4)
# TypeError: myfunc() takes exactly 3 arguments (4 given)
Azat Ibrakov
11.1k9 gold badges43 silver badges58 bronze badges
answered Jul 2, 2012 at 11:15

6 Comments

Yes, I saw it and it seems to be exactly what I'm after. But I don't know how to create/modify function body and return values..?
I just tryed it, when you change the call at the end with the correct nb of args, it segfault...
Did you ever try to execute this code? Because this code can't run.
yeah func_Code attribute doesn't exist in python 3.
The original post said, "Did you see this?". However, the original webpage is dead now. There is no http://snipplr.com/view/17819/.
|
34

If you need to dynamically create a function from a certain template try this piece:

def create_a_function(*args, **kwargs):
 def function_template(*args, **kwargs):
 pass
 return function_template
my_new_function = create_a_function()

Within function create_a_function() you can control, which template to chose. The inner function function_template serves as template. The return value of the creator function is a function. After assignment you use my_new_function as a regular function.

Typically, this pattern is used for function decorators, but might by handy here, too.

answered Nov 11, 2015 at 16:30

2 Comments

Thank you! Exactly what I was looking for. My use case was to create a function based on one of my dynamic generated class attribute. But it should not depend on 'self'. Therefore it is a static func create_a_function with the parameter as an argument. Thereby the attribute can be used in the inner function as a normal variable and the function is detached :-)
it has some limit, can't be serialized by pickle
14

You can use lambda for this.

a = lambda x: x + 1
>>> a(2)
3
Asclepius
64.5k20 gold badges188 silver badges164 bronze badges
answered Nov 29, 2017 at 10:35

2 Comments

This is almost the one I'm using now. In my case I need to dynamically build a function as a string or to precompile a configured string expression, so I used a = eval("lambda x: x + 1") instead, but the result is the same. In my case I also provide math functions to expressions, so I also added from math import * in the python scripts that evaluate and execute the lambda.
Note that you can use this to create a list or dict of functions that can be run like generic['d'](3)
9

What about this approach?

In this example I'm parametrizing first order functions on one variable (x -> ax+b) in one class:

class Fun: 
 def __init__(self, a,b):
 self.a, self.b = a,b
 def f(self, x):
 return (x*self.a + self.b)
 u = Fun(2,3).f

Here u will be the function x->2x+3.

answered Jul 17, 2015 at 10:36

1 Comment

there's always functools.partial applied to lambdas as well: u = partial(lambda a, b, x: x*a + b, 2, 3)
4

You can do at this manner:

new_func='def next_element(x):\n return x+1'
the_code=compile(new_func,'test','exec')
exec(the_code)
next_element(1)

It's similar to the previous exec solution.

answered Feb 4, 2020 at 13:22

Comments

1

simpler than Berci's answer

def get_fn(a, b): # factory function
 def fn(): # result function
 print(a, b)
 return fn
fn = get_fn(1, 2)
fn()

this is useful to turn variables into constants ("template variables for dynamic functions")

answered Dec 10, 2021 at 14:50

Comments

1

In my case I need a function returning the function to save it into a variable:

def create_function(function_name, function_arguments, function_code):
 function_string = f"def {function_name}({function_arguments}): {function_code}"
 exec(function_string)
 return_value = eval(function_name)
 return return_value
name = 'say_hello'
arguments = 'name'
code = 'print(f"Hello, {name}!")'
myfunc = create_function(name, arguments, code)
print(myfunc, type(myfunc))
myfunc('John Doe')
answered Dec 28, 2022 at 12:51

Comments

1

for the sake of completeness, the way how dynamically created function works can be simply parametrized

def dynamically_create_greeting(greet_style):
 def inner(name):
 print(f'{greet_style} {name}')
 return inner
say_hello = dynamically_create_greeting(greet_style='hello')
say_hello('John')
say_hi = dynamically_create_greeting(greet_style='hi')
say_hi('John')

this produces output >

hello John

hi John

answered Jan 22, 2023 at 14:17

4 Comments

Hi, can you explain, how it works? It looks like the greet_style parameter is passed to the function before it's called, what is the explanation? Thanks!
Note these are separate functions and parameters. First is dynamically_create_greeting() function, and you pass the 'greet_style' in there as a parameter. That will just dynamically create (without executing it) inner function what will behave based on that parameter, and returns it. In the example above we will refer to the returned functions using 'say_hello' and 'say_hi'. Then, you actually call (execute) say_hello() itself, what accepts it's own parameter - 'name'.
Yeah, I understand the functions are created dynamically. What I don't understand is how and where the "greet_style" parameter is stored. Because when we call say_hello and say_hi, we pass only the name but not the greet_style.
It's not stored in a sense of a an object having member you can interact with or change. You create a function and it behaves in some way, it does 'something'. So you create it (dynamically in this case) with how to do 'something' built-in. It's 'stored' in the same way as print function behavior to display smt on a console is 'stored' somewhere so print does exactly that and not something else ( if that's where are you heading, your function behavior ("greet_style) is 'stored' somewhere in your active python session's memory, look for 'inspect' module for this low level operations)

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.