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

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


当前回答

不,我不相信有任何方法可以在Python中前向声明一个函数。

假设您是Python解释器。当你走到排队的时候

print "\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])

您可能知道cmp_configs是什么,也可能不知道。为了继续,你必须 知道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模块来比较这两个语句,它们具有完全相同的计算成本。

当然,这里的例子是非常无用的,但如果有一个复杂的结构,需要执行一个函数,但必须在之前声明(或者在结构上,之后声明没有什么意义),可以只存储一个字符串,然后尝试调用函数。

# declare a fake function (prototype) with no body
def foo(): pass

def bar():
    # use the prototype however you see fit
    print(foo(), "world!")

# define the actual function (overwriting the prototype)
def foo():
    return "Hello,"

bar()

输出:

Hello, world!

Python不支持前向声明,但常见的解决方法是在脚本/代码的末尾使用以下条件:

if __name__ == '__main__': main()

这样,它将首先读取整个文件,然后计算condition并调用main()函数,该函数将能够调用任何前向声明的函数,因为它已经首先读取了整个文件。此条件利用特殊变量__name__,当我们从当前文件运行Python代码时,该变量返回__main__值(当代码作为模块导入时,__name__返回模块名)。

“重新组织我的代码,这样我就不会有这个问题了。”正确的。很容易做到。总是工作。

您总是可以在引用函数之前提供该函数。

“然而,在某些情况下,这可能是不可避免的,例如在实现某些形式的递归时”

我看不出这有什么可能。请举例说明在使用之前不能定义函数的地方。

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

import test

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