如何提前声明函数以避免后面的`NameError`?

279 投票
17 回答
259323 浏览
提问于 2025-04-15 15:11

在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_conditionend_result 是之前定义过的。

难道唯一的解决办法就是重新组织代码,总是把定义放在调用之前吗?

17 个回答

116

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

if __name__=="__main__":
   main()

那么你可能不需要担心像“前向声明”这样的事情。你看,解释器会先加载你所有的函数,然后再开始执行你的 main() 函数。当然,确保你所有的导入都正确哦;-)

想想看,我在 Python 中从来没听说过“前向声明”这种说法……不过我也可能错了;-)

195

把调用的部分放到一个自己的函数里,这样

foo()

def foo():
    print "Hi!"

就会出错,但

def bar():
    foo()

def foo():
    print "Hi!"

bar()

就能正常工作。

在Python中,一般的规则是函数应该在使用之前定义,这并不一定意味着它必须在代码的上面。

87

如果你不想在使用一个函数之前就定义它,而在之后定义又不行,那你可以考虑在其他模块里定义这个函数。

从技术上讲,你还是先定义了它,但这样做看起来更整洁。

你可以创建一个像下面这样的递归:

def foo():
    bar()

def bar():
    foo()

Python里的函数就像值一样是匿名的,但它们可以绑定到一个名字上。

在上面的代码中,foo()并不是在调用一个叫foo的函数,而是在调用一个在调用时恰好绑定到名字foo的函数。你可以在其他地方重新定义foo,这样bar就会调用新的函数。

你的问题无法解决,因为这就像是在要求获取一个还没有声明的变量一样。

撰写回答