是否有可能在Python中前向声明一个函数?我想在声明之前使用我自己的cmp函数对列表进行排序。
print "\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])
我把cmp_configs方法的定义放在调用之后。它会失败,报错如下:
NameError: name 'cmp_configs' is not defined
是否有任何方法在使用cmp_configs方法之前“声明”它?
有时候,很难重新组织代码来避免这个问题。例如,在实现某些形式的递归时:
def spam():
if end_condition():
return end_result()
else:
return eggs()
def eggs():
if end_condition():
return end_result()
else:
return spam()
其中end_condition和end_result已经在前面定义。
唯一的解决方案是重新组织代码并始终在调用之前放置定义吗?
现在等一下。当您的模块到达示例中的print语句时,在定义cmp_configs之前,您到底希望它做什么?
如果你用print发布的问题实际上是想表达这样的东西:
fn = lambda mylist:"\n".join([str(bla)
for bla in sorted(mylist, cmp = cmp_configs)])
那么在执行这条语句之前就不需要定义cmp_configs了,只要在后面的代码中定义它就可以了。
现在如果你试图引用cmp_configs作为lambda参数的默认值,那么这是一个不同的故事:
fn = lambda mylist,cmp_configs=cmp_configs : \
"\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])
现在,您需要在到达这一行之前定义一个cmp_configs变量。
[EDIT -接下来的部分被证明是不正确的,因为默认参数值将在函数编译时被赋值,即使您稍后更改cmp_configs的值,该值也将被使用。]
幸运的是,Python是如此适应类型,并不关心你定义什么为cmp_configs,所以你可以用这句话开始:
cmp_configs = None
这样编译器就高兴了。只要确保在调用fn之前声明真正的cmp_configs即可。
我很抱歉恢复这个话题,但有一个策略没有在这里讨论,但可能适用。
使用反射可以做一些类似于前向声明的事情。例如,假设你有这样一段代码:
# We want to call a function called 'foo', but it hasn't been defined yet.
function_name = 'foo'
# Calling at this point would produce an error
# Here is the definition
def foo():
bar()
# Note that at this point the function is defined
# Time for some reflection...
globals()[function_name]()
因此,通过这种方式,我们已经确定了在实际定义函数之前要调用哪个函数,这实际上是一种前向声明。在python中,由于上述原因,如果function_name = 'foo',语句globals()[function_name]()与foo()相同,因为python必须在调用每个函数之前查找它。如果使用timeit模块来比较这两个语句,它们具有完全相同的计算成本。
当然,这里的例子是非常无用的,但如果有一个复杂的结构,需要执行一个函数,但必须在之前声明(或者在结构上,之后声明没有什么意义),可以只存储一个字符串,然后尝试调用函数。
现在等一下。当您的模块到达示例中的print语句时,在定义cmp_configs之前,您到底希望它做什么?
如果你用print发布的问题实际上是想表达这样的东西:
fn = lambda mylist:"\n".join([str(bla)
for bla in sorted(mylist, cmp = cmp_configs)])
那么在执行这条语句之前就不需要定义cmp_configs了,只要在后面的代码中定义它就可以了。
现在如果你试图引用cmp_configs作为lambda参数的默认值,那么这是一个不同的故事:
fn = lambda mylist,cmp_configs=cmp_configs : \
"\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])
现在,您需要在到达这一行之前定义一个cmp_configs变量。
[EDIT -接下来的部分被证明是不正确的,因为默认参数值将在函数编译时被赋值,即使您稍后更改cmp_configs的值,该值也将被使用。]
幸运的是,Python是如此适应类型,并不关心你定义什么为cmp_configs,所以你可以用这句话开始:
cmp_configs = None
这样编译器就高兴了。只要确保在调用fn之前声明真正的cmp_configs即可。