【问题标题】:More functional python更多功能的python
【发布时间】:2012-04-19 19:08:34
【问题描述】:

我想编写一种 CPS 代码的高级函数。他们应该获取一个功能代码,将其封装在对象中,并添加组合这些对象的方法。

类似这样的:

myFunction=MyFunction(
  a = b+c
  print(c)
  return a)

但是对于匿名函数,只有一个 Python 表达式—— lambda 语句。它不太适合。

Python 是一门强大的语言,它有不同的表达方式:装饰器、eval 等......有没有像上面提到的例子那样编写匿名函数的好方法?

另一种方法是使用特殊函数(如 monadic bind 和 return)扩展 lambda 表达式,以及用于编写单行复杂表达式的其他高阶函数。

主要目的是创建自定义的抛出控制表达式。

class TimeoutExpression:
  def __init__(self,name,function,timeout):
    ...
  def eval(self):
    """ eval functions, print result and error message
      if functions failed to calculate in time """
    ...
  def andThen(self,otherExpression):
    """ create complex sequential expression"
    ...
  def __call__(self):
    ...

它的使用方式如下:

TimeoutExpression( time consuming calculation ).andThen(
  file object access).andThen(
    other timer consuming calcualtion )

创建自定义控制流构造的最佳 Python 惯用方式是什么?

我已阅读讨论:How to make an anonymous function in Python without Christening it? 提到了几个采用相同方法的决定:从三重引号字符串生成函数。 虽然行为完全正确,但似乎很麻烦。它是目前设计的最佳方法吗?

更新

有人告诉我没有问题,python 允许你在任何上下文中使用 def。我假设我的 python 经验欺骗了我,并尝试按照建议在任何范围内使用 def 。我有一个错误。我应该如何将 def 放在任何上下文中?

def compose(f):
    return lambda k: lambda x: f(k(x))

test = compose( def sqr(x) :
                print ("sqr "+str(x))
                return x*x
                return sqr) ( def x2(x):
                              print("x2 "+str(x))
                              return x*2
                              return x2 )

错误:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "anonFunction.py", line 4
    test = compose( def sqr(x) :
                  ^
SyntaxError: invalid syntax

【问题讨论】:

  • 为什么一定要匿名?
  • 复杂单行不适合python zen
  • 每种语言都不同。不要尝试使用 Python 编写函数式代码,就像用另一种语言编写函数式代码一样。

标签: python functional-programming anonymous-function


【解决方案1】:

使用 lambda 的 w.r.t Python 没有任何优势。 Lambda 和 Anonymous 函数一般用于简单函数,如果需要更复杂的多行函数,编写命名函数更易读。

由于函数是第一类对象,您可以简单地定义它,将它分配给一个变量,然后使用它并传递它。 除非您需要一个可以选择 lambda 的一次性简单函数,否则命名函数是有利的。尽管如此,在从未完全 Pythonic 中使用 lambda。

回到你的例子,

myFunction=MyFunction(
  a = b+c
  print(c)
  return a)

在 Python 中,写法类似

def MyFunction:
    a =b + c
    print c
    return a

然后将它作为MyFunction 传递给你的代码是相当Pythonic 的。我在 Javascripts 中看到了 Callbacks 以匿名方式编写的代码。但是每种语言都有自己的哲学,而 Python 的哲学是可读性。

---可读性很重要。

【讨论】:

  • 命名函数在被名字多次使用时很有用。我想写这样的东西:Fun(some expr).bind(some expr).bind(other expr) 用于创建非标准控制流,例如并行执行或超时计算等。
  • @ayvango:即使是一次性使用命名函数也不错。
  • @ayvango 另请注意,您可以在任何您想要的范围内使用def,而不仅仅是在顶层;他们也有完全关闭等等。拥有“多行 lambdas”并没有太大的优势;唯一的区别是你不能直接把它写成另一个函数的参数,这在语法上通常很混乱。
  • @Dougal 你能举例说明在任何范围内使用 def 吗?我在问题中添加了我的示例
  • @ayvango 对不起,当我说“任何范围”时,我并不是指“任何地方”;我认为这只是允许完整语句的地方,而不是像你的例子中的表达式。你会在那里做的是把def sqrdef x2作为独立的表达式,然后传入sqrx2;我的意思是你可以在另一个def 中做一个def 并使用封闭范围内的东西。
【解决方案2】:

在 Python 中,使用 lambda 关键字,您只能创建一个计算单个表达式并返回结果的函数对象。要使用语句或多行创建函数,必须使用 def 关键字,该关键字需要名称。

lambda进行限制的原因主要是基于Python将行尾视为一件重要的事情:

No Multiline Lambda in Python: Why not?

但是,名称并不重要。您可以制定一个约定,即您的每个“匿名”函数都将使用名称 anon 或其他名称进行定义。如果你真的在乎,你可以抹去名字的所有痕迹:

y = 5
def anon(x):
    return x + y  # note "closure" over the current value of y

myFunction = anon

# if you really care, you can erase all evidence of name "anon"
anon.__name__ = ''  # wipe the record of original name "anon"
del(anon)  # unbind the name "anon"

因此,对于函数式编程,Python 可以创建一流的函数对象,传递它们等等。Python 不能做的一件事是创建一个没有名称的复杂函数对象,但实际上没有理由这样做应该很重要。

【讨论】:

  • Python 可以使用 lambda 编程技术创建具有 lambda 结构的任意复杂函数对象,但它相当烦人,只有在没有其他选择时才应使用(例如 lisp)
  • 好吧,律师模式已启用:不再说您可以编写“简单函数”,而是说“您只能创建一个评估单个表达式并返回结果的函数对象。”是的,可以使用复杂的表达式来编写复杂的函数对象,但这将是一个非常糟糕的主意,或者正如您所说,“相当烦人,只有在没有其他选择的情况下才应该使用”。
【解决方案3】:

我有一个技巧——这确实是唯一合适的术语——使用嵌套函数,它提供了多行 lambda 可能提供的功能。您可以查看我的 GitHub 存储库here

基本上它允许您执行以下操作:

fibonacci = f('result = t(a-1)+t(a-2) if a>2 else 1; return result')
fibonacci(6) #Output: 8

或者更多的匿名函数:

cube = f('result = a**3; return result')(4)
print(cube) #Output: 64

这个 hack 显然有局限性;例如,我还没有想出一种方法来实现更复杂的缩进结构,如ifwhile,但同样,这是一个非常便宜的 hack。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-25
    • 1970-01-01
    • 2019-06-02
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    相关资源
    最近更新 更多