2013-08-04 50 views
4
>>> list=[None] 
>>> def list[0](x,y): 
    File "<stdin>", line 1 
    def list[0](x,y): 
      ^
SyntaxError: invalid syntax 

如何将函数定义为列表元素?将函数定义为列表元素

+1

你到底想干什么?我认为你想要的是你不应该做的事情,但即使如此,我不知道你在问什么 – TerryA

+4

为什么这么多用户低估了这个合法的问题让我印象深刻。 – Hyperboreus

+1

这是一个完全合法的问题。其他一些语言确实允许通用的左值(不仅仅是标识符)作为函数定义的目标。 OP合理地认为Python可能支持功能定义目标中的类似灵活性。 –

回答

11

Python的def不够灵活,无法处理通用lvalues,如list[0]。该语言只允许您使用标识符作为函数名称。下面是grammar rule for the def-statement的相关部分:

funcdef  ::= "def" funcname "(" [parameter_list] ")" ":" suite 
funcname  ::= identifier 

相反,你可以使用一系列的分配和定义语句:

s = [None] 

def f(x, y): 
    return x + y 

s[0] = f 

作为替代方案,你也可以直接存储lambda expression在列表:

​​
9
def f(whatever): 
    do_stuff() 

l[0] = f 

函数定义语法不允许您直接定义一个函数到数据结构,但你可以创建功能,那么无论它需要去指定。

+0

或'l = []; l.append(f)' – SethMMorton

+2

@SethMMorton:或者只是'l = [f]'如果你正在控制'l'的创建,而不是试图将函数分配到现有的位置,但我认为这会更清晰。 – user2357112

4
def someFunctionA(x, y): 
    return x+y 

def someFunctionB(x, y): 
    return x*y 

someList = [someFunctionA, someFunctionB] 

print someList[0](2, 3) 
print someList[1](5, 5) 
+2

为什么不'l = [someFunctionA,someFunctionB]'? (此外,最好不要使用'list'作为标识符。) – glglgl

+0

我这样做了,但有一个错误,并认为lambda是必要的。现在它可以工作,但显然lambda是多余的。 +1! – Akinakes

+3

我认为关于使用'list'作为标识符的投诉是站得住脚的。阴影列表不好。 – tacaswell

2

允许这样的自由将使解析较硬的......例如括号表达式

...(x, y, z=3) 

可以是参数声明(其中3为关键字参数z缺省值)或呼叫(即传递z关键字参数值作为3)。

如果你想允许def通用分配表示你还需要允许

def foo(x, y, z=3)[3](x, y, z=3): 
    ... 

,其中第一个括号部分具有从第二部分不同的语义和语法规则。

为此编写一个解析器很烦人(基本上是因为你需要处理一个任意的无限量的源代码而不理解它),这就是例如导致我知道的整个宇宙中最差的解析规则(这是可怕的C++的most vexing parse),基本上放弃了试图通过辞退歧义来获得体面的语言。

请注意,在很多情况下,当程序难以进行解析时,这是因为含糊不清,会让人难以理解它。

Python正确地将可读性看作非常重要。在Python

函数是但第一类对象,所以你可以解决你的问题很容易就够了:

def foo(...): 
    ... 

mylist[index] = foo 

或者,只有当函数是一个单一的表达,与

mylist[index] = lambda ... : ... 

(但lambda是非常有限的,这既是因为它在Python社区中有点“讨厌”,也因为它会在语法级别造成一些烦恼,因为需要处理括号内的缩进)。

还要注意,一些Python新手不知道的是,即使在函数内部也可以使用def;例如:

def register_http(): 
    def handle_http(connection): 
     ... 
    global_register['http'] = handle_http 

将分配一个功能作为全局地图的元件,而不与它的名称污染全局(模块)的命名空间。本地def也可以通过捕获本地状态变量(在2.x中为只读,甚至在3.x中读/写)来创建闭包。

还要注意,如果你需要一些功能的处理可能是decorators可能是有用的。例如通过定义

def register(name): 
    def do_registering(f): 
     global_register[name] = f 
     return f 
    return do_registering 

你可以使用

@register('http') 
def handle_http(connection): 
    ... 
+0

你是完全正确的,但是,我必须对这样一个复杂的事情是必要的事实咆哮。有一个非常好的语法元素:装饰器。他们可以很容易地用于此。我有时做的是返回或产生一个函数,但装饰器不适用于语句。然而,'@ return'或'@ yield'应该是相当不错的。在这种情况下,我们可以在这之前有一个'@ = target'(因为分配目标位于右边而会变得丑陋),或者'@@ target',比如'@@ global_register ['http']'函数,在函数之后不需要丑陋的赋值/产量/返回行。 – glglgl

+0

@glglgl:你可以做比使用'@register('http')''等参数化装饰器更简单的事情。他们有点奇怪的实现(参数化装饰器必须返回一个非参数化的装饰器函数),但他们很好用。请参阅编辑。 – 6502

+0

对,在这种情况下,这是一个不错的选择;我忘了那个。但是,唉,不能用于简化“yield”或“return”之类的东西。 – glglgl

相关问题