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:
functools.partial()
(ie to create a wrapper function with one extra parameter that is not yet known) self
a meaningful keyword or would lambda spam
would work just as well? .check()
is perfectly fine outside the class
es scope? lambda
(not to mention that I agree with Guido and Alex that it is an eyesore and I want to do without :) 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() (ie 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.
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
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
.
- Is the lambda used here to perform the exact opposite of
functools.partial()
(ie 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)
- 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.
- What point is that lambda evaluated?
lambda
creates anonymous function, which as any function is evaluated upon call.
- 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.