Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the lambda self: do

This answer explains how to create test cases dynamically.

The answer's code:

class Tests(unittest.TestCase):
    def check(self, i, j):
        self.assertNotEquals(0, i-j)

for i in xrange(1, 4):
    for j in xrange(2, 6):
        def ch(i, j):
            return lambda self: self.check(i, j)
        setattr(Tests, "test_%r_%r" % (i, j), ch(i, j))

I've tested and it works, but I can't just figure out how?

I have trouble understanding the lambda self: magic in play here, mainly:

  1. Is the lambda used here to perform the exact opposite of functools.partial() (i.e. to create a wrapper function with one extra parameter that is not yet known)
  2. Is self a meaningful keyword or would lambda spam would work just as well?
  3. What point is that lambda evaluated?
  4. How come the .check() is perfectly fine outside the classes scope?
  5. How do you do this without lambda? - if I understand correctly, you should be able to do without lambda (not to mention that I agree with Guido and Alex that it is an eyesore and I want to do without :)
like image 773
Kimvais Avatar asked Apr 27 '12 07:04

Kimvais


People also ask

What does command lambda do?

Lamda Functions (also referred to as Anonymous Function in Python) are very useful in building Tkinter GUI applications. They allow us to send multiple data through the callback function. Lambda can be inside any function that works as an anonymous function for expressions.

What does lambda do in Haskell?

λ-expressions (λ is the small Greek letter lambda) are a convenient way to easily create anonymous functions — functions that are not named and can therefore not be called out of context — that can be passed as parameters to higher order functions like map, zip etc.

Can lambda return anything?

Lambda functions are syntactically restricted to return a single expression. You can use them as an anonymous function inside other functions. The lambda functions do not need a return statement, they always return a single expression.

When should lambda be used?

Use a Lambda when you need to access several services or do custom processing. As data flows through services, you use Lambdas to run custom code on that data stream. This is useful in a Kinesis Pipeline that's receiving data from things like IoT devices.


3 Answers

First of all: The lambda is returned from a function to prevent that modified values of i and j will be used later.

Compare to the following:

for i in xrange(1, 4):
    for j in xrange(2, 6):
        setattr(Tests, "test_%r_%r" % (i, j), lambda self: self.check(i, j))

This will not work as expected, as all the lambdas will share the same namespace and will use the values of i and j after the end of the loop. If we use a separate function call, we introduce a new closure every time that captures the values of i and j at the point in time where the function is called.

We could achieve the same by saving the current values of i and j as default arguments of the lambda. For good measure, let's also use itertools.product to avoid the nested loop:

from itertools import product
from operator import methodcaller

for i, j in product(range(1, 4), range(2, 6)):
  setattr(Tests, "test_%r_%r" % (i, j),
          lambda self, i=i, j=j: self.check(i, j))

Is the lambda used here to perform the exact opposite of functools.partial() (i.e. to create a wrapper function with one extra parameter that is not yet known)

Not really. It just calls the check(i, j) method on whatever it is given as an argument. This is used here to dynamically add methods to the Tests class.

Is self a meaningful keyword or would lambda spam would work just as well?

spam would work just as well. They choose self here due to convention because the lambda represents a method.

What point is that lambda evaluated?

As soon as test_[i]_[j]() is called on an instance of Tests.

How come the .check() is perfectly fine outside the classes scope?

Because it's inside a lambda will only be called later with an instance of Tests as the self argument.

like image 118
Niklas B. Avatar answered Nov 03 '22 02:11

Niklas B.


a_function = lambda x: do_something_with(x)

is equivalent to

def a_function(x):
    return do_something_with(x)

In your particular example, the functions created are instance methods. Thus for example you could write:

class Tests:
...
   test_1_2 = lambda self: self.check(1, 2)

which would be equivalent to:

class Tests:
...
   def test_1_2(self):
       return self.check(1, 2)

Now, since the identifiers are generated dynamically, hence use of setattr.


  1. Is the lambda used here to perform the exact opposite of functools.partial() (i.e. to create a wrapper function with one extra parameter that is not yet known)

No, not really. In fact partial could be used here as well.

test_1_2 = lambda self: self.check(1, 2)

would became

test_1_2 = partial(Tests.check, i=1, j=2)
  1. Is self a meaningful keyword or would lambda spam would work just as well?

Instance method's first argument always needs to be the instance. The convention is to name that parameter self, but you can use any other name. I would not advise it, as it will make your code harder to read and understand.

  1. What point is that lambda evaluated?

lambda creates anonymous function, which as any function is evaluated upon call.

  1. How come the .check() is perfectly fine outside the classes scope?

It isn't. It's self.check(), where self is an instance of Tests class.

like image 24
vartec Avatar answered Nov 03 '22 02:11

vartec


lambda returns a function. self is its argument, and i and j are enclosed inside of it

So, ch(i, j) is a function of i and j which returns a function of self.

self does not have any magical meaning here as nothing in Python - every variable and function are explicit except of some built-ins. But as soon as these methods are attached to class, self becomes their 1st argument.

This means

  • after the loop The Tests class gets multiple methods called check_i_j

  • each of them has values i and j enclosed in it

  • each of them has their 1st param called self which is good cause they are defined inside of class, they are instance methods, and thus their 1st parameter should be called self by convention

like image 35
Guard Avatar answered Nov 03 '22 02:11

Guard