是否有可能在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已经在前面定义。

唯一的解决方案是重新组织代码并始终在调用之前放置定义吗?


当前回答

如果对cmp_configs的调用在它自己的函数定义中,那么应该没有问题。我举个例子。

def a():
  b()  # b() hasn't been defined yet, but that's fine because at this point, we're not
       # actually calling it. We're just defining what should happen when a() is called.

a()  # This call fails, because b() hasn't been defined yet, 
     # and thus trying to run a() fails.

def b():
  print "hi"

a()  # This call succeeds because everything has been defined.

一般来说,把你的代码放在函数中(比如main())会解决你的问题;只需在文件末尾调用main()即可。

其他回答

将调用包装到它自己的函数中,以便

foo()

def foo():
    print "Hi!"

会破碎,但

def bar():
    foo()

def foo():
    print "Hi!"

bar()

将正常工作。

Python中的一般规则是,函数应该在使用之前定义,这并不一定意味着它需要在代码中处于更高的位置。

现在等一下。当您的模块到达示例中的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即可。

在python中没有像前向声明这样的东西。您只需确保在需要函数之前声明了它。 注意,函数体在执行之前不会被解释。

考虑下面的例子:

def a():
   b() # won't be resolved until a is invoked.

def b(): 
   print "hello"

a() # here b is already defined so this line won't fail.

您可以认为函数体只是另一个脚本,在调用该函数后将对其进行解释。

导入文件本身。假设文件名为test.py:

import test

if __name__=='__main__':
    test.func()
else:
    def func():
        print('Func worked')

如果你通过以下方式启动你的脚本:

if __name__=="__main__":
   main()

那么你可能就不必担心“向前声明”之类的事情了。你看,解释器会加载你所有的函数,然后启动你的main()函数。当然,也要确保所有的导入都是正确的;-)

仔细想想,我从来没有在python中听到过“前向声明”这样的东西……但话说回来,我可能错了;-)