Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

True dynamic and anonymous functions possible in Python?

Tags:

python

Just as a dynamic class can be created using type(name, base-classes, namespace-dict), can a dynamic function be created?

I've tried doing something along the lines of:

>>> f = type("f", (function,), {}) NameError: name 'function' is not defined 

Ok, so I'll be clever, but:

>>> def fn(): ...   pass ...  >>> type(fn) <type 'function'> >>> f = type("f", (type(fn),), {}) Traceback (most recent call last):   File "<stdin>", line 1, in <module> TypeError: type 'function' is not an acceptable base type 

Does Python specifically prevent the creation of dynamic functions in the same way it allows dynamic classes?

Edit: Note, I'd disallow any use of exec.. Since my question is does the Python language itself permit this.

Thanks in advance.

like image 813
Bill VB Avatar asked Apr 24 '12 17:04

Bill VB


People also ask

Does Python have anonymous functions?

In Python, an anonymous function is a function that is defined without a name. While normal functions are defined using the def keyword in Python, anonymous functions are defined using the lambda keyword. Hence, anonymous functions are also called lambda functions.

What is dynamic function in Python?

Python's built-in exec() executes the Python code you pass as a string or executable object argument. This is called dynamic execution because, in contrast to normal static Python code, you can generate code and execute it at runtime. This way, you can run programmatically-created Python code.

How do you call an anonymous function in Python?

The lambda keyword is used to define anonymous functions in Python. Usually, such a function is meant for one-time use.

What are anonymous functions and how can they be used?

Anonymous functions are often arguments being passed to higher-order functions, or used for constructing the result of a higher-order function that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function.


2 Answers

There is types.FunctionType which you can use to dynamically create a function e.g.

def test_func(): print 'wow'  dynf = types.FunctionType(test_func.func_code, {}) dynf() 

Output:

wow 

You might object that this is not dynamic because I am using code from another function, but that was just an example there is a way to generate code from python strings e.g.

dynf = types.FunctionType(compile('print "really WoW"', 'dyn.py', 'exec'), {}) dynf() 

Output:

really WoW 

Now that is dynamic!

OP is worried about the dynamic nature of such function so here is another example

dynf = types.FunctionType(compile('test_func():\ntest_func()', 'dyn.py', 'exec'), globals()) dynf() 

Output:

wow wow 

Note: Creating Function object like this seems to have limitations e.g. it is not easy to pass arguments, because to pass arguments we need to pass correct co_argcount, co_varnames and other 12 variables to types.CodeType, which theoretically can be done but will be error prone, an easier way is to import string as a module and you have a full fledged function e.g.

import types import sys,imp  code = """def f(a,b,c):     print a+b+c, "really WoW" """ module = imp.new_module('myfunctions') exec code in module.__dict__ module.f('W', 'o', 'W') 

Output:

WoW really WoW 
like image 136
Anurag Uniyal Avatar answered Oct 05 '22 01:10

Anurag Uniyal


You'll want to look into collections.Callable, which is just a good place to start when defining __call__.

from collections import Callable class SomeCallableClass(Callable):     def __call__(self, x):         print(x)  some_function = SomeCallableClass() some_function(1) 

Will give us 1 as out output. This allows you to construct functions at will.

from collections import Callable class SomeCallableClass(Callable):     def __init__(self, n):         self.n = n     def __call__(self, x):         for i in range(self.n):             print(x)  some_function = SomeCallableClass(2) some_function("Two times.") some_function = SomeCallableClass(3) some_function("Three times.") 

Which gives us:

Two times. Two times. Three times. Three times. Three times. 

You can use this to construct functions as complex as you want.

like image 22
Gareth Latty Avatar answered Oct 05 '22 01:10

Gareth Latty