【问题标题】:Why does assigning lambdas not work as expected in Python 3.5?为什么在 Python 3.5 中分配 lambda 不能按预期工作?
【发布时间】:2016-01-29 10:57:45
【问题描述】:

我知道 Python 应该具有一流的函数,并且我已经编写了一些 Python 来“确认”这一点,但是以下内容会在 3.5 中爆炸(耗尽堆栈深度)我的 IDLE:

k = lambda x:x+1
k = lambda x:k (x+1)
k(0)

它不应该评估为 2 吗?

k = lambda x:x+1
j = lambda x:k (x+1)
j(0)

确实如此。

【问题讨论】:

  • 您是说它在 IDLE 中触发了无限递归(我可以相信),还是应该正确评估为无限循环(这不是我所期望的)?如果是后者,我希望第二行中的 RHS k 评估回第一行中的 lambda,将k 更新为lambda x: (x+1)+1。 (我很高兴得知 CS 的其他成员不会期望这种情况。)
  • lambda 是“后期绑定”。在调用 lambda 之前不会检查 k 的值

标签: python-3.x lambda


【解决方案1】:

使用lambda 进行可视化

稍微打印一下可能有助于了解发生了什么:

k = lambda x: x+1
print('before:', id(k))
k = lambda x: print('in    :', id(k))
k(0)
print('after :', id(k))

before: 4428659024
in    : 4428658208
after : 4428658208

最后一个lambdaid 和里面的用法一样。这很好地展示了后期绑定。

翻译成函数语句

如果您将lambdas 转换为使用def 定义的函数,事情可能会更清楚:

def k(x):
    return x + 1

def k(x):
    return k(x+1)
k(0)

很明显,第一个定义确实有意义,因为它被第二个覆盖了。

此外,即使您为函数使用不同的名称并重新分配函数名称:

def k(x):
    return x + 1

def j(x):
    return k(x+1)

k = j

似乎更清楚的是,第一个函数定义没有意义,因为永远无法访问该函数。

【讨论】:

  • 另外,PEP8 规定您根本不应该绑定 lambda:“始终使用 def 语句而不是直接将 lambda 表达式绑定到标识符的赋值语句。”所以作为一个风格指南,OP 应该避免他们正在尝试的东西。
  • @Dalum 好点。你总是可以用def 来做这件事,而且通常会更好。这两行可以使事情更容易理解。我仍然记得关于从 Python 3 中删除 lambda 的激烈讨论。
【解决方案2】:

k 的名称查找是在运行时完成的,这意味着该函数会无限次调用自身(并且第一行没有任何用处)。如果你想要你期望的结果,那么你将不得不使用三元运算符来立即返回而不是递归。

【讨论】:

  • 对不起,是哪个三元运算符(我只知道“if 表达式”)。 (谷歌搜索似乎只会把它打开)
  • 是的,那将是 Python 的三元运算符。
猜你喜欢
  • 1970-01-01
  • 2011-01-04
  • 2021-05-30
  • 2020-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多