Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lambda in python

I'm revisiting some scheme excercises in python (if that makes sense) to find out what python can do in terms of FP. My problem concerns lambda in python : Can i define a general function in python with an operator as one of the arguments?

Think this :

def f (op,x,y):
    #return some lambda function that combines x and y in the appropriate way
    #i.e if op is +, then return x+y, if op is -, then return x-y etc

#Edit : added usage
#this should be called like this:
f(+, 1,2) #should return 3

I know this is possible in scheme, but is there something equivalent in python? I've gotten the impression that lambda in python is just a shorter way of defining a method, and I've not found any way to define a general combiner function in python.

like image 533
Arnab Datta Avatar asked Nov 02 '11 00:11

Arnab Datta


2 Answers

I can see some points in your question, lets go through them in order:

1. Can I pass a function as a parameter to someone?

Yes:

def f(op, x, y):
    return op(x, y)

def add(x, y):
    return x + y

f(add, 10, 7) #gives 17

2. What about operators then?

Unlike scheme, Python operators are not functions so you can't pass them directly as parameters. You can either create the wrapper functions yourself or you can import the operator module from the standard library.

import operator

operator.add(1, 2)
(lambda x,y : x+y)(1, 2)

Operators not being real functions is a little sad in most cases but at least Python gives us chained comparisons like 10 <= x < 100 in exchange...

3. So what is the difference between Python and Scheme then?

In the general sense, functions in Python are as powerful as functions in Scheme, however there are some things to note:

The lambda keyword is limited

You can only have a single expression as the function body

f = lambda x, y: x + y

Since there are a bunch of things in Python that are statements and not expressions (assignments, the 2.x print, ...), you often need to fall back to named functions instead.

There are closures

def make_printer(msg):
    def printer():
        print msg
    return printer

printer('a message')()

But mutating variables in them is a pain

This doesn't work. It tries to bind a new n for the inner function instead of using the outer one

def make_counter(n):
    def inc():
        n = n + 1
        return n
    return inc

new 3.x nonlocal keyword

def make_counter(n):
    def inc():
        nonlocal n
        n = n + 1
        return n
    return inc

workaround w/ mutable objects

def make_counter(n):
    nw = [n]
    def inc():
       nw[0] = nw[0] + 1
       return nw[0]
    return inc

Objects instead of closures. Uses the magic __call__ method to pretend its a function

class Counter:
    def __init__(self, n):
        self.n = n
    def __call__(self):
        self.n += 1
        return self.n
like image 140
hugomg Avatar answered Sep 20 '22 14:09

hugomg


Operators aren't really function in python, more like methods -- x + y is short for x.__add__(y), or y.__radd__(x). You can use the functions in the operator module to emulate the behavior you want.

like image 42
Ismail Badawi Avatar answered Sep 21 '22 14:09

Ismail Badawi