关于python:lambda self:做什么

What does the lambda self: do

这个答案解释了如何动态创建测试用例。

答案的代码:

1
2
3
4
5
6
7
8
9
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))

我已经测试过它的确有效,但我不知道怎么做?

我无法理解这里的lambda self:魔法,主要是:

  • 这里使用的lambda是否与functools.partial()完全相反(即使用一个尚未知的额外参数创建包装函数)
  • self是一个有意义的关键字还是lambda spam同样适用?
  • lambda评估的重点是什么?
  • 为什么.check()class范围之外完全没问题?
  • 没有lambda你怎么做? - 如果我理解正确,你应该可以不用lambda(更不用说我同意Guido和Alex这是一个眼睛,我想没有:)

  • 首先:从函数返回lambda,以防止稍后使用ij的修改值。

    与以下内容比较:

    1
    2
    3
    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))

    这将无法按预期工作,因为所有lambda将共享相同的命名空间,并将在循环结束后使用ij的值。如果我们使用单独的函数调用,每次在调用函数的时间点捕获ij的值时,我们会引入一个新的闭包。

    我们可以通过将ij的当前值保存为lambda的默认参数来实现相同的目的。为了更好的衡量,我们还使用itertools.product来避免嵌套循环:

    1
    2
    3
    4
    5
    6
    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)

    并不是的。它只是在作为参数给出的任何内容上调用check(i, j)方法。这里用于向Tests类动态添加方法。

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

    spam也可以。由于约定,它们在这里选择self,因为lambda代表一种方法。

    What point is that lambda evaluated?

    只要在Tests的实例上调用test_[i]_[j]()

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

    因为它在lambda中只会稍后使用Tests的实例作为self参数调用。


    a_function = lambda x: do_something_with(x)

    相当于

    1
    2
    def a_function(x):
        return do_something_with(x)

    在您的特定示例中,创建的函数是实例方法。因此,例如你可以写:

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

    这相当于:

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

    现在,由于标识符是动态生成的,因此使用setattr

  • 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)
  • 不,不是真的。实际上partial也可以在这里使用。

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

    会成为

    1
    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方法的第一个参数总是需要是实例。约定是将参数命名为self,但您可以使用任何其他名称。我不建议它,因为它会使你的代码更难阅读和理解。

  • What point is that lambda evaluated?
  • lambda创建匿名函数,在调用时评估任何函数。

  • How come the .check() is perfectly fine outside the classes scope?
  • 事实并非如此。它是self.check(),其中selfTests类的实例。


    lambda返回一个函数。 self是它的参数,i和j被包含在其中

    因此,ch(i,j)是i和j的函数,它返回self的函数。

    self在Python中没有任何神奇的含义 - 除了一些内置函数之外,每个变量和函数都是显式的。但是只要这些方法附在课堂上,自我就成了他们的第一个论点。

    这意味着

    • 循环之后The Tests类获取多个名为check_i_j的方法

    • 它们中的每一个都包含值i和j

    • 他们每个都有第一个名为self的参数,这是很好的因为它们是在类中定义的,它们是实例方法,因此它们的第一个参数应该按照约定被称为self