Friday, June 15, 2012

Python Lambda Intro (with simple example)

While really a simple thing to do, I wanted to post an example of a very simple program using something a little less common. Instead of the more common way of making a function, I will instead use lambda. In Python, lambda is used for passing an anonymous functions to a method or can be used to have a function generate simple functions. For the latter, decorators can be used for a more complex function generation, however I have yet to fully grasp using it, so I'll save explaining that for when I know how to practically use it.

Now anonymous functions are cool because you can either pass them to a function without creating some permanent function that will only be used in that one particular instance or you can pass it to a variable reference. Passing to variable reference is as simple as defining any variable. The difference in this particular instance is that lambda is limited to very simple functions, and returning variables is not as clear as a return statement. Let's view a quick example.

import sys

ftoc = lambda(f): (f-32.0)*(5.0/9.0)
ctof = lambda(c): (9.0/5.0)*c+32.0

while(1):
    try:
        print """Pick a conversion (EOF to end ctrl+z win/ctrl+c *nix)
1 - Fahrenheit to Celsius
2 - Celsius to Fahrenheit
3 - Exit

>""",
        choice = raw_input()

        if choice == 3:
            break;
        else:
            print "What is the tempurature?",
            temp = raw_input()
            if choice == "1":
                print str(ftoc(float(temp)))+" Celsius"
            elif choice == "2":
                print str(ctof(float(temp)))+" Fahrenheit"
            else:
                print "Unknown option"

    except KeyboardInterrupt:
        break;

    except Exception as e:
        print "An error occured: "+str(e)
print "Goodbye."
exit(0)


The main point to focus on is the 2 lines following the import statements. To break it down, ftoc = lambda(f): (f-32.0)*(5.0/9.0) is actually very simple. It starts out with a normal variable declaration, variable name being ctof. We then assign it to the value of the lambda statement. The word lambda in Python means an anonymous function, then the (x) is the arguments the function accepts. This does not need to be in parenthesis can could just as easily be lambda x:. I use the parentheses to more clearly show that it's not the function name, but arguments being passed to it, I find it to be more clear for myself reading it. The next part is just a formula for converting the temperature. The question may arise, where is the return value? Quite simply, it's whatever the code in the lambda statement evaluates to at the very end.

Now some caveats. Lambda functions cannot span multiple lines, it's only a 1 liner function (with the exception being if a docstring is used). It also supports nested scope, so if it is within a scope where it uses a variable name, it will use that variable, however if the variable is the name of an argument variable, that value will be used instead. Finally, semicolons are ending delimiters and cannot be used to include multiple lines of code, it is only a single statement.

One more little catch I ran into, while I doubt anyone has a need for it, trying to define a list of lambda functions through list comprehension will not work to make different functions. Using something like y = [lambda (x): x+z for z in range(10)] will result in all 10 list items having z as 9 because it will use z as a reference to z and not replace the value, therefore the last value of z is the one that is used. However, if you replace the lambda function with a function that returns lambda functions, it works, and looks like this.

def a(x):
    return lambda(y): x+y

y = [a(z) for z in range(10)]


I was also informed of an alternative way to do this through default values, which looks a little uglier, but can condense things if you really want to. You can do something like y = [(lambda x, z=z: x+z) for z in range(10)], which will place the value of z as the default argument. Note however, that since it is a default argument, it can then be changed, which does not seem like a clean solution.

No comments:

Post a Comment

Tag Cloud

.NET (2) A+ (5) ad ds (1) addon (4) Android (4) anonymous functions (1) application (9) arduino (1) artificial intelligence (1) backup (1) bash (6) camera (2) certifications (3) comptia (5) css (2) customize (11) encryption (3) error (13) exploit (5) ftp (1) funny (4) gadget (4) games (3) GUI (5) hardware (16) haskell (6) help (14) HTML (3) imaging (2) irc (1) it (1) java (2) javascript (13) jobs (1) Linux (19) lua (1) Mac (4) malware (1) math (6) msp (1) network (13) perl (2) php (3) plugin (2) powershell (8) privacy (2) programming (24) python (10) radio (2) regex (3) repair (2) security (16) sound (2) speakers (2) ssh (1) story (5) Techs from the Crypt (5) telnet (1) tools (13) troubleshooting (11) tutorial (9) Ubuntu (4) Unix (2) virtualization (2) web design (6) Windows (16) world of warcraft (1) wow (1) wx (1)