2012-04-19 120 views
1

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

事情是这样的:

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

但只有一个匿名函数Python的表达 - 拉姆达声明。它适合不太好。

Python是一种功能强大的语言,它有不同的表达式:装饰器,eval等...有没有一种好的方法来编写像上面例子中的匿名函数?

其他方法是扩展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。我有一个错误。我应该如何在任何情况下放置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 
+4

为什么它必须是匿名的? – KillianDS 2012-04-19 19:10:19

+0

复杂和单行不适合python zen – KurzedMetal 2012-04-19 19:11:04

+6

每种语言都不一样。不要试图用Python来编写功能代码,就像用另一种语言完全一样。 – agf 2012-04-19 19:11:07

回答

3

有使用拉姆达的w.r.t Python中没有优势。 Lambda和Anonymous函数通常用于简单函数,并且如果您需要更复杂的多行函数,则它更具可读性来编写命名函数。

由于函数是第一类对象,您可以简单地定义它,将其分配给一个变量并使用它并传递它。 除非另有说明,否则您需要一个一次性的简单函数,您可以选择lambda的函数,命名的函数是有利的。不过也使用lambda在从未完全Pythonic。

回来到您的例子,

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

在Python,写它类似于

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

,然后通过它在你的代码为MyFunction很Python的。我在Javascript中看到了回调书写为匿名的代码。但是每种语言都有自己的哲学,Python的哲学是可读性。

---可读性计数。

+0

如果多于一次使用名称,则命名函数很有用。我想写这样的:Fun(某些expr).bind(某些expr).bind(其他expr)用于创建非标准控制流,例如并行执行或超时计算等。 – ayvango 2012-04-19 19:16:21

+0

@ayvango:即使使用命名函数进行单次使用也不是一个坏的选择。 – Abhijit 2012-04-19 19:21:18

+1

@ayvango还要注意,你可以在你想要的任何范围内使用'def',而不仅仅是在顶层;他们也有完全关闭等等。“多线lambda”没有多大优势;唯一的区别是你不能直接把它作为另一个函数的参数来写,它通常在语法上相当混乱。 – Dougal 2012-04-19 19:26:45

1

在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不能做的就是创建一个复杂的函数对象,从来没有一个名字,但真的没有理由为什么这很重要。

+0

Python可以使用lambda编程技术创建具有lambda结构的任意复杂函数对象,但这很麻烦,应该只有在没有其他选择的情况下才能使用(例如,lisp) – ayvango 2012-04-19 19:50:05

1

我有一个破解 - 这是真正的唯一正确的术语 - 使用嵌套函数,提供多线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 

明明有这个黑客限制;例如,我仍然没有想出一种方法来实现更复杂的缩进结构,如ifwhile,但再次,这是一个非常便宜的黑客。