Showing posts with label dynamic-code. Show all posts
Showing posts with label dynamic-code. Show all posts

Sunday, December 23, 2018

Dynamic function creation at run time with Python's eval built-in

By Vasudev Ram



Hi, readers,

A few days ago, I had published this post:

Dynamic function creation at run time with Python's exec built-in

In today's post I'll show another way of dynamically creating functions at run time - this time using Python's eval built-in instead of exec.

I'll show the code (dyn_func_with_eval.py), followed by its output.
# dyn_func_with_eval.py 
# Purpose: To dynamically create (and run) a function at run time, 
# using Python's eval built-in.
# Author: Vasudev Ram
# Copyright 2018 Vasudev Ram
# Web site: https://vasudevram.github.io
# Product store: https://gumroad.com/vasudevram
# Twitter: https://twitter.com/vasudevram

from __future__ import print_function

expr = raw_input("Enter a function of x: ")
print("expr: ", expr)
g = eval("lambda x: " + expr)
print("g:", g)
print("g.func_code.co_argcount:", g.func_code.co_argcount)
print("g.func_code.co_varnames:", g.func_code.co_varnames)
print("g(0):", g(0))

old_gi = 0
for i in range(5):
    gi = g(i)
    diff = gi - old_gi
    print("i = {}, g({}) = {}, diff = {}".format(i, i, gi, diff))
    old_gi = gi
As you can see, after prefixing the expression (that was input by the user) with "lambda x: ", to make it a complete lambda function definition, the program uses eval() (instead of exec() like last time), to dynamically evaluate the entered expression (which should represent a function of x).

The end result is that the lambda function object is created and then bound to the name g. Then g is used in the remaining code.

The values of g and g(0) are printed.

Then, in a loop, g is evaluated for i ranging from 0 to 4. For each such value, i, g(i) and the difference between the old g(i) and the current one is printed. (No meaningful value can be given for the previous value of g(i) before g(0), so I used 0 arbitrarily; ignore that first difference).

Now, the output:
$ python dyn_func_with_eval.py
Enter a function of x: x * x + 2 * x + 1
expr:  x * x + 2 * x + 1
g: <function <lambda> at 0x022D0A70>
g.func_code.co_argcount: 1
g.func_code.co_varnames: ('x',)
g(0): 1
i = 0, g(0) = 1, diff = 1
i = 1, g(1) = 4, diff = 3
i = 2, g(2) = 9, diff = 5
i = 3, g(3) = 16, diff = 7
i = 4, g(4) = 25, diff = 9

Note that I used Python introspection to print the argument count and the local variable names of the generated function.

So, it worked. We could enter a function of x via the keyboard, use eval() to dynamically create a Python function that uses it, and evaluate that function for some range of values. Are there any uses of this technique, other than to show that it is possible, and interesting? Sure, I can think of at least one: a graphing calculator. We could have a GUI window with a pane that can draw graphics, such as curves in the 2D plane (using one of the Python GUI toolkits like wxPython or PyQt that support this), and then repeatedly prompt the user for a function of x, eval() it as above, then plot the values of x and y (= g(x)) for a range, in a loop, to draw a curve that represents the function entered.

Note: Use of exec and eval can be a security risk, so only use them in a trusted environment. The optional arguments globals and locals, which I did not use in these two posts, may be of use to control the environment in which they run, but user input is also important.

In fact, the graphing calculator could probably be done as a web app too, using some Python web framework, such as Flask, Bottle, Django or other (a lightweight one may be better here, or even plain CGI), and a web form with an HTML5 canvas and some JavaScript on the front-end. The user could enter the formula (some function of x) in a text box, submit it, the back-end Python app could eval() it to create the function, evaluate that function for a range of points like I did above, and send the list of (x, y) pairs to the browser, where the JavaScript could draw a curve representing those points, on the canvas.

Did you notice any pattern to the values of g(i)? The values are 1, 4, 9, 16, 25 - which are the squares of the integers 1 to 5. But the formula I entered for g was not x * x, rather, it was x * x + 2 * x + 1. Then why are squares shown in the output? Reply in the
comments if you get it, otherwise I will answer next time.

The image at the top of the post is from the Wikipedia page about lambda (the Greek letter) and is of the Greek alphabet on a black figure vessel. Check out the many meanings and uses of the symbol/letter lambda in various fields (see that Wikipedia page).

- Enjoy.


- Vasudev Ram - online Python training and consulting


I conduct online courses on Python programming, Unix / Linux commands and shell scripting and SQL programming and database design, with course material and personal coaching sessions.

The course details and testimonials are here.

Contact me for details of course content, terms and schedule.

Getting a new web site or blog, and want to help preserve the environment at the same time? Check out GreenGeeks.com web hosting.

Sell your digital products via DPD: Digital Publishing for Ebooks and Downloads.

Learning Linux? Hit the ground running with my vi quickstart tutorial. I wrote it at the request of two Windows system administrator friends who were given additional charge of some Unix systems. They later told me that it helped them to quickly start using vi to edit text files on Unix. Of course, vi/vim is one of the most ubiquitous text editors around, and works on most other common operating systems and on some uncommon ones too, so the knowledge of how to use it will carry over to those systems too.

Check out WP Engine, powerful WordPress hosting.

Creating online products for sale? Check out ConvertKit, email marketing for online creators.

Teachable: feature-packed course creation platform, with unlimited video, courses and students.

Posts about: Python * DLang * xtopdf

My ActiveState Code recipes

Follow me on:



Sunday, December 16, 2018

Dynamic function creation at run time with Python's exec built-in

By Vasudev Ram

Hi, readers,
I was browsing Paul Graham's essay about his book "On Lisp". It's about advanced uses of Lisp and some of the features that make it unique.

In it, he talks about many Lisp features, like the ability to treat code as data, the fact that functions are first-class objects, so, just like other objects such as scalar variables, lists, maps, etc., they too can be passed as arguments to functions, returned from functions, stored in variables, etc., and the fact that Lisp programs can write Lisp programs. (There's a lot more to the book, of course.) This made me think of experimenting a bit with Python's dynamic features, whether similar to Lisp or not. One man's Lisp is another man's Python ...

I did know from a while ago that Python has many dynamic features, and have blogged about some of them in the past. (Search my blog for topics like Python tricks, the trace module and chained decorators, Python introspection, the inspect module, finding the caller of a Python function, Python generators are pluggable, function-based callbacks, class-based callbacks, and other fun stuff. Try using 'site:jugad2.blogspot.com' and suchlike search engine techniques.) This is one more such exploration.

I got the idea of writing a program that can dynamically create a function at run time, based on some user input, and then run that function. The program uses the exec built-in of Python.

Here is the program, dyn_func_with_exec.py:
# dyn_func_with_exec.py 
# Purpose: To dynamically create (and run) a function at run time. 
# Author: Vasudev Ram
# Copyright 2018 Vasudev Ram
# Web site: https://vasudevram.github.io
# Product store: https://gumroad.com/vasudevram

from __future__ import print_function
import sys

major = sys.version_info.major
if major == 2:
    input_func = raw_input
elif major == 3:
    input_func = input
else:
    print("Unsupported version, go back to the future.")
    sys.exit(0)

func_name = input_func("Enter name of function to create dynamically: ")
func_def = """
def {}(args):
    print("In function", func_name, ": args:", args)
""".format(func_name)

exec(func_def)
print(func_name, ":", eval(func_name))

args1 = (1, "a"); args2 = (2, "b")

# Two ways of calling the dynamically created function:
print("\nCalling {} via eval():".format(func_name))
eval(func_name + "(args1)")
print("\nCalling {} via globals() dict:".format(func_name))
globals()[func_name](args2)
Here is the output of 3 runs:
(py is the Python launcher for Windows.)
$ py -2 dyn_func_with_exec.py
Enter name of function to create dynamically: mu
mu : <function mu at 0x0000000002340518>

Calling mu via eval():
In function mu : args: (1, 'a')

Calling mu via globals() dict:
In function mu : args: (2, 'b')

$ py -3 dyn_func_with_exec.py
Enter name of function to create dynamically: _
_ : <function _ at 0x000000000039C1E0>

Calling _ via eval():
In function _ : args: (1, 'a')

Calling _ via globals() dict:
In function _ : args: (2, 'b')

$ py dyn_func_with_exec.py
Enter name of function to create dynamically: |
Traceback (most recent call last):
  File "dyn_func_with_exec.py", line 28, in <module>
    exec(func_def)
  File "<string> line 2
    def |(args):
        ^
SyntaxError: invalid syntax
So it works in both Python 2 and 3. The last run (with an invalid function name) shows how the user input gets interpolated into the function definition string func_def.

The if statement used shows another dynamic aspect of Python: the ability to call different functions (via the same name, input_func), based on some condition which is only known at run time (the Python version, in this case).

Why mu for the input? Well, if foo, why not mu? :)
See my HN comment here

Another way to dynamically decide which function to run:

Driving Python function execution from a text file

Enjoy.


- Vasudev Ram - Online Python training and consulting

I conduct online courses on Python programming, Unix / Linux commands and shell scripting and SQL programming and database design, with course material and personal coaching sessions.

The course details and testimonials are here.

Contact me for details of course content, terms and schedule.

Try FreshBooks: Create and send professional looking invoices in less than 30 seconds.

Getting a new web site or blog, and want to help preserve the environment at the same time? Check out GreenGeeks.com web hosting.

Sell your digital products via DPD: Digital Publishing for Ebooks and Downloads.

Learning Linux? Hit the ground running with my vi quickstart tutorial. I wrote it at the request of two Windows system administrator friends who were given additional charge of some Unix systems. They later told me that it helped them to quickly start using vi to edit text files on Unix. Of course, vi/vim is one of the most ubiquitous text editors around, and works on most other common operating systems and on some uncommon ones too, so the knowledge of how to use it will carry over to those systems too.

Teachable: feature-packed course creation platform, with unlimited video, courses and students.

Check out WP Engine, powerful WordPress hosting.

Creating online products for sale? Check out ConvertKit, email marketing for online creators.

Get a fast web site with A2 Hosting.

Posts about: Python * DLang * xtopdf

My ActiveState Code recipes

Follow me on: