lambda self:做什么

时间:2012-04-27 07:05:32

标签: python lambda functional-programming

This answer解释了如何动态创建测试用例。

答案的代码:

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:魔法,主要是:

  1. 这里使用的lambda是否与functools.partial()完全相反(即创建一个包含 extra 参数的包装函数尚未知道)
  2. self是一个有意义的关键字,还是lambda spam也能正常运作?
  3. lambda评估的重点是什么?
  4. 为什么.check()class范围之外完全正常?
  5. 你如何做没有 lambda? - 如果我理解正确,you should be able to do without lambda(更不用说我同意Guido和Alex认为 是一个眼睛,我希望没有:)< / LI>

3 个答案:

答案 0 :(得分:5)

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

与以下内容比较:

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来避免嵌套循环:

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))
  

这里使用的lambda是否与functools.partial()完全相反(即创建一个包含一个尚未知的额外参数的包装函数)

不是真的。它只是调用check(i, j)方法作为参数。这用于动态地将方法添加到Tests类。

  

自我是一个有意义的关键字还是lambda垃圾邮件也能正常工作?

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

  

lambda评估的重点是什么?

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

  

为什么.check()在类范围之外完全没问题?

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

答案 1 :(得分:3)

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

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

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

这意味着

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

  • 每个人都有值i和j 封闭

  • 他们每个都有第一个名为self的参数,这是好的,因为它们是在类中定义的,它们是实例方法,因此它们的第一个参数应该按惯例调用自我

答案 2 :(得分:3)

a_function = lambda x: do_something_with(x)

相当于

def a_function(x):
    return do_something_with(x)

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

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

这相当于:

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

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


  
      
  1. 这里使用的lambda是否与functools.partial()完全相反(即创建一个额外的包装函数)   参数尚未知晓)
  2.   

不,不是真的。事实上,partial也可以在这里使用。

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

会变成

test_1_2 = partial(Tests.check, i=1, j=2)
  
      
  1. 自我是一个有意义的关键字还是lambda垃圾邮件也能正常工作?
  2.   

实例方法的第一个参数始终需要是实例。 约定是命名该参数self,但您可以使用任何其他名称。我不建议它,因为它会使你的代码更难阅读和理解。

  
      
  1. lambda评估的重点是什么?
  2.   

lambda创建匿名函数,在调用时评估任何函数。

  
      
  1. 为什么.check()在类范围之外完全没问题?
  2.   

不是。它是self.check(),其中selfTests类的实例。