Showing posts with label lambda. Show all posts
Showing posts with label lambda. 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:



Thursday, April 27, 2017

Using nested conditional expressions to classify characters

By Vasudev Ram


While writing some Python code, I happened to use a conditional expression, a Python language feature.

Conditional expressions are expressions (not statements) that have if/else clauses inside them, and they evaluate to either one of two values (in the basic case), depending on the value of a boolean condition. For example:
for n in range(4):
    print n, 'is odd' if n % 2 == 1 else 'is even'
0 is even
1 is odd
2 is even
3 is odd
Here, the conditional expression is this part of the print statement above:
'is odd' if n % 2 == 1 else 'is even'
This expression evaluates to 'is odd' if the condition after the if is True, and evaluates to 'is even' otherwise. So it evaluates to a string in either case, and that string gets printed (after the value of n).

Excerpt from the section about conditional expressions in the Python Language Reference:

[
conditional_expression ::= or_test ["if" or_test "else" expression]
expression ::= conditional_expression | lambda_expr

Conditional expressions (sometimes called a “ternary operator”) have the lowest priority of all Python operations.

The expression x if C else y first evaluates the condition, C (not x); if C is true, x is evaluated and its value is returned; otherwise, y is evaluated and its value is returned.
]

You can see that the definition of conditional_expression is recursive, since it is partly defined in terms of itself (via the definition of expression).

This implies that you can have recursive or nested conditional expressions.

Also, since the syntax of the Python return statement is:
return [ expression_list ]
(where expression_list means one or more expressions, separated by commas, it follows that we can use a nested conditional expression in a return statement (because a nested conditional expresssion is an expression).

Here is a small program to demonstrate that:
'''
File: return_with_nested_cond_exprs.py 
Purpose: Demonstrate nested conditional expressions used in a return statement, 
to classify letters in a string as lowercase, uppercase or neither.
Also demonstrates doing the same task without a function and a return, 
using a lambda and map instead.
Author: Vasudev Ram
Copyright 2017 Vasudev Ram
Web site: https://vasudevram.github.io
Blog: https://jugad2.blogspot.com
'''

from __future__ import print_function
from string import lowercase, uppercase

# Use return with nested conditional expressions inside a function, 
# to classify characters in a string as lowercase, uppercase or neither:
def classify_char(ch):
    return ch + ': ' + ('lowercase' if ch in lowercase else \
    'uppercase' if ch in uppercase else 'neither')

print("Classify using a function:")
for ch in 'AaBbCc12+-':
    print(classify_char(ch))

print()

# Do it using map and lambda instead of def and for:
print("Classify using map and lambda:")

print('\n'.join(map(lambda ch: ch + ': ' + ('lowercase' if ch in lowercase else 
'uppercase' if ch in uppercase else 'neither'), 'AaBbCc12+-')))
Running it with:
$ python return_with_nested_cond_exprs.py
gives this output:
Classify using a function:
A: uppercase
a: lowercase
B: uppercase
b: lowercase
C: uppercase
c: lowercase
1: neither
2: neither
+: neither
-: neither

Classify using map and lambda:
A: uppercase
a: lowercase
B: uppercase
b: lowercase
C: uppercase
c: lowercase
1: neither
2: neither
+: neither
-: neither
As you can see from the code and the output, I also used that same nested conditional expression in a lambda function, along with map, to do the same task in a more functional style
.

- Vasudev Ram - Online Python training and consulting

Get updates (via Gumroad) on my forthcoming apps and content.

Jump to posts: Python * DLang * xtopdf

Subscribe to my blog by email

My ActiveState Code recipes

Follow me on: LinkedIn * Twitter

Are you a blogger with some traffic? Get Convertkit:

Email marketing for professional bloggers



Thursday, October 25, 2012

Site: Stupid lambda tricks in Python

By Vasudev Ram


Stupid lambda tricks in Python, on the site www.p-nand-q.com. Seen via a friend. The site also has some other Python stuff.

- Vasudev Ram - Dancing Bison Enterprises