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

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


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

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

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

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


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

if __name__=="__main__":
   main()

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

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


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

foo()

def foo():
    print "Hi!"

会破碎,但

def bar():
    foo()

def foo():
    print "Hi!"

bar()

将正常工作。

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


如果您不想在使用函数之前定义它,并且在使用之后定义它是不可能的,那么在其他模块中定义它呢?

从技术上讲,您仍然先定义它,但它是干净的。

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

def foo():
    bar()

def bar():
    foo()

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

在上面的代码中,foo()并不调用foo名称的函数,它调用的函数恰好在调用时绑定到foo名称。可以在其他地方重新定义foo,然后bar将调用新函数。

您的问题无法解决,因为这就像要求获得一个未声明的变量。


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

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

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

您可能知道cmp_configs是什么,也可能不知道。为了继续,你必须 知道cmp_configs。不管有没有递归。


如果对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()即可。


在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.

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


现在等一下。当您的模块到达示例中的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中不能前向声明函数。如果在定义函数之前已经执行了逻辑,那么无论如何都可能遇到问题。将你的动作放在脚本末尾的if __name__ == '__main__'中(通过执行一个你命名为“main”的函数,如果它不是平凡的),你的代码将更加模块化,如果你需要,你将能够将它作为一个模块使用。

同样,用生成器表达式替换该列表理解(即,打印"\n".join(str(bla) for bla in sorted(mylist, cmp=cmp_configs)))

另外,不要使用已弃用的cmp。使用键并提供小于函数。


有时,算法最容易自上而下地理解,从整体结构开始,深入到细节。

你可以在没有前向声明的情况下这样做:

def main():
  make_omelet()
  eat()

def make_omelet():
  break_eggs()
  whisk()
  fry()

def break_eggs():
  for egg in carton:
    break(egg)

# ...

main()

一种方法是创建处理程序函数。尽早定义处理程序,并将处理程序放在需要调用的所有方法的下面。

然后,当您调用处理程序方法来调用函数时,它们将始终可用。

处理程序可以接受一个名为ofmethodtocall的参数。然后使用一堆if语句来调用正确的方法。

这将解决你的问题。

def foo():
    print("foo")
    #take input
    nextAction=input('What would you like to do next?:')
    return nextAction

def bar():
    print("bar")
    nextAction=input('What would you like to do next?:')
    return nextAction

def handler(action):
    if(action=="foo"):
        nextAction = foo()
    elif(action=="bar"):
        nextAction = bar()
    else:
        print("You entered invalid input, defaulting to bar")
        nextAction = "bar"
    return nextAction

nextAction=input('What would you like to do next?:')

while 1:
    nextAction = handler(nextAction)

我很抱歉恢复这个话题,但有一个策略没有在这里讨论,但可能适用。

使用反射可以做一些类似于前向声明的事情。例如,假设你有这样一段代码:

# 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模块来比较这两个语句,它们具有完全相同的计算成本。

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


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

import test

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

# 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不需要前向声明。只需将函数调用放在函数定义中,就可以了。

def foo(count):
    print("foo "+str(count))
    if(count>0):
        bar(count-1)

def bar(count):
    print("bar "+str(count))
    if(count>0):
        foo(count-1)

foo(3)
print("Finished.")

递归函数定义,完美成功地给出:

foo 3
bar 2
foo 1
bar 0
Finished.

然而,

bug(13)

def bug(count):
    print("bug never runs "+str(count))

print("Does not print this.")

中断尚未定义的函数的顶级调用,并给出:

Traceback (most recent call last):
  File "./test1.py", line 1, in <module>
    bug(13)
NameError: name 'bug' is not defined

Python是一种解释型语言,就像Lisp一样。它没有类型检查,只有运行时函数调用,如果函数名已绑定,则调用成功,如果未绑定则调用失败。

重要的是,函数定义不会在它的行中执行任何funcall,它只是声明函数体将由什么组成。同样,它甚至不做类型检查。所以我们可以这样做:

def uncalled():
    wild_eyed_undefined_function()
    print("I'm not invoked!")

print("Only run this one line.")

它运行得非常好(!),有输出

Only run this one line.

关键在于定义和调用之间的区别。

解释器执行顶层的所有内容,这意味着它尝试调用它。如果它不在定义中。 您的代码遇到了麻烦,因为您试图在绑定函数之前在顶层调用函数。

解决方案是将非顶级函数调用放在函数定义中,然后在很久以后的某个时候调用该函数。

“如果__主要__”是基于这一原则的习语,但你必须理解为什么,而不是简单地盲目地遵循它。

当然还有关于lambda函数和动态重绑定函数名的更高级的主题,但这些不是OP所要求的。此外,它们可以使用这些相同的原则来解决:(1)defs定义一个函数,它们不调用它们的行;(2)当你调用一个未绑定的函数符号时,你会遇到麻烦。


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

if __name__ == '__main__': main()

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


Python在技术上支持前向声明。

如果你定义了一个函数/类,然后将函数体设置为pass,那么它在全局表中将有一个空条目。

然后,您可以“重新定义”函数/类,以实现函数/类。

与c/c++前向声明不同的是,这不能在作用域外(即另一个文件)工作,因为它们有自己的“全局”命名空间

例子:

def foo(): pass

foo()

def foo(): print("FOOOOO")

foo()

两次都声明了Foo 然而,第一次调用foo时,它没有做任何事情,因为body只是传递 但是第二次调用foo。它执行新的打印体("FOOOOO")

但再一次。注意,这不会修复循环依赖关系。这是因为文件有自己的名称和自己的函数定义

示例2:


class bar: pass

print(bar)

这将打印<class '__main__。Bar '>,但如果它在另一个文件中声明,它将是<class 'otherfile.foo'>

我知道这篇文章很旧了,但我认为这个答案对任何在张贴多年后仍然找到这篇文章的人都是有用的