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

时间:2011-01-23 23:18:16

标签: python

在尝试理解如何使用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晃动它很棒”

Facebook的问题陈述是:

您已截获了一系列使用有趣且愚蠢的方法加密的传输,您已设法解密。消息仅包含空格和小写英文字符,并按如下方式加密:对于句子中的所有单词,第i个单词(从1开始)的单词将替换为通过应用以下递归操作生成的单词f(word,i) :

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

如果单词具有奇数长度,则将其拆分以使右侧更长。您决定与发送邮件的人一起玩,并以他们正在使用的相同风格广播您自己的邮件。

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

输出 在应用上述编码方法之后,对每种情况输出并用换行符分隔加密语句的内容。您可以忽略传统的大小写规则并坚持使用所有小写字母。

约束 5≤N≤25 句子不超过100个字符。

2 个答案:

答案 0 :(得分:3)

哇,这是一个丑陋的Python系列:)

函数和lambdas之间的唯一区别:您可以在定义它的同一行上使用lambda。没有办法定义一个普通的函数,并且在不使用exec或类似的不推荐的东西的情况下在一行中间调用它。

函数与lambda的示例 - 以下实现大致相当:

# the shortest numbers of lines required to define and call a normal function: 2
def foo(bar): return bar
print foo('baz')

# this lambda has the exact same effect as the function "foo" above
foo = lambda bar: bar

# the shortest number of lines required to define and call a lambda: 1
# note you can also call the lambda on the same line you define it
# and you aren't required to even name a lambda
print (lambda bar: bar)('baz')

Lambdas允许您编写非常难以阅读的代码。例如:

a = (lambda x: x+x)(1) # very long-winded way of saying "a = 1+1"

关于Facebook的问题,让我们分解吧。

# for simplicity, let's say we're getting a single string
# with a sentence on each line.
text = '''
stackoverflow rocks and is great
redundancy is the redundant king of the land
without a foo, you cannot bar the baz
'''

# first, we'll strip() the text to remove the spaces at the edges
# as these would create blank lines when splitting the text
text = text.strip()

# next, we'll split the text on the newline character, '\n'
lines = text.split('\n')

# now we have a list of lines, which we can easily walk through with a for loop
for line in lines:
     # now we're going to split all of the words from each line
     # this is easy, just split with a space as the delimiter
     words = line.split(' ')

     # then we want to sort the words alphabetically
     # list.sort() will easily sort a list in place
     words.sort()

     # now we want to recombine the line
     # we're going to use join() for this
     # we call join on a string, with a list: like 'foo'.join(list)
     # join combines the list into a string
     # placing the string between each item

     # we're going to join with a blank string
     # so our words will be all in a row with no spaces
     sentence = ''.join(words)

     # that's it! now we can just print the sorted result
     print sentence

结果如下:

andgreatisrocksstackoverflow
iskinglandofredundancyredundantthethe
abarbazcannotfoo,thewithoutyou

这些是有条理的词:

and great is rocks stackoverflow
is king land of redundancy redundant the the
a bar baz cannot foo, the without you

几乎是诗意的:)

作为参考,这是我对Facebook问题的原始解决方案:

import sys
q = open(sys.argv[1]).read().strip()
for line in q.split('\n')[1:]:
    print ''.join(sorted(line.split(' ',1)[1].split(' ')))

我一般建议不要使用lambdas。这是我的单行版本,仅使用列表理解和加入/拆分:

print '\n'.join([''.join(sorted(line.split(' '))) for line in text.split('\n') if line])

答案 1 :(得分:2)

Python lambdas只是语法糖。 “Regular”函数具有相同的功能,例如闭包,因为,请记住,您可以在另一个函数中定义它们,就像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对象时,它的名称设置为“&lt; lambda&gt;”,而不是如上所述的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)

这段代码是fixed-point combinator的一个例子,我几乎无法理解,而且在不知道更多上下文的情况下很难给出更好的名称(我没有尝试破译实际的问题陈述)。它可以解析为直接通过名称调用自身的递归函数。