将lambda转换为Python中的普通函数

3 投票
1 回答
1556 浏览
提问于 2025-04-16 10:29

在我试图理解如何使用lambda表达式的时候,我看到一个回复,里面说用lambda能做的事情,用普通函数也都能做到。

我一直在努力尝试在Python中调用一个函数自己去执行,虽然我不是专家,但我在学习中遇到了一些需要用递归函数的情况,这种函数需要多次调用才能得到特定的答案。

有一个人用lambda函数来解决这个问题,我试着去理解,但没成功。所以我想,如果用普通函数来实现这个功能,可能会更容易理解lambda的用法。

我们以这个句子为例:

print"\n".join(" ".join([(lambda f:(lambda x:f(lambda*r:x(x)(*r)))(lambda x:f(lambda*r:x(x)(*r))))(lambda f:lambda q,n:len(q)<=n and q or f(q[len(q)/2:],n)+f(q[:len(q)/2],n))(k,z+1)for z,k in enumerate(i[:-1].split())]) for i in list(s)[1:])

这个问题在Facebook的黑客杯中被使用过,我没能解决这个问题,因为我在循环中迷失了。

这个句子包含几个单词,比如说“Stackoverflow rocks and it is great”。

Facebook中的问题描述是:

你拦截了一系列用一种有趣又愚蠢的方法加密的传输信息,你已经成功解密了这些信息。消息只包含空格和小写字母,且加密方式如下:对于句子中的每个单词,第i个单词(从1开始计数)会被替换成通过以下递归操作f(word, i)生成的单词:

如果单词的长度小于或等于i, 就返回这个单词。 否则,返回f(单词的右半部分, i) + f(单词的左半部分, i)。

如果单词长度是奇数,则右边的部分会更长。你决定和发送消息的人开个玩笑,自己也用他们的加密风格发送消息。

输入 你的输入将以一个整数N开始,接着是换行符,然后是N个测试用例。每个用例由一个未加密的句子组成,句子只包含空格和小写字母,且用例之间用换行分隔。句子中不会有前导或尾随空格,且相邻字符之间最多只有1个空格。

输出 对于每个用例,输出加密后的句子内容,并用换行分隔。你可以忽略传统的大小写规则,全部使用小写字母。

约束条件 5 ≤ N ≤ 25 句子最多包含100个字符。

1 个回答

3

Python中的lambda表达式其实就是一种语法上的简化。普通的函数也能做同样的事情,比如闭包,因为你可以在一个函数里面定义另一个函数,这和lambda的做法是一样的。

def some_func():
  some_expr_using(lambda args: 42)

# becomes:

def some_func():
  def unique_name(args):
    return 42
  some_expr_using(unique_name)

不过,当你查看lambda对象时,它的名字会显示为“<lambda>”,而不是像上面那样的unique_name,其他一些细节也是关于源代码的书写方式,而不是它的实际行为。

你的代码可以写成:

def y(f):
  def a(x):
    def b(*r):
      return x(x)(*r)
    return f(b)
  return a(a)

def fx(f):
  def x(q, n):
    # changed "a and b or c": different semantics if b can be falsy
    if len(q) <= n:
      return q
    else:
      return f(q[len(q) / 2:], n) + f(q[:len(q) / 2], n)
  return x

print "\n".join(
  " ".join(y(fx)(k, z + 1) for z, k in enumerate(i[:-1].split()))
  for i in list(s)[1:])

(但这得看我翻译得对不对,最好再检查一下。:P)

这段代码是一个不动点组合子的例子,我对这个概念了解得不多,想给它起个更好的名字也很难,因为我不知道更多的上下文(我没有尝试去理解实际的问题陈述)。它可以被展开成一个递归函数,这个函数可以直接通过名字调用自己。

撰写回答