是否有可能在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不需要前向声明。只需将函数调用放在函数定义中,就可以了。
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)当你调用一个未绑定的函数符号时,你会遇到麻烦。
我很抱歉恢复这个话题,但有一个策略没有在这里讨论,但可能适用。
使用反射可以做一些类似于前向声明的事情。例如,假设你有这样一段代码:
# 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模块来比较这两个语句,它们具有完全相同的计算成本。
当然,这里的例子是非常无用的,但如果有一个复杂的结构,需要执行一个函数,但必须在之前声明(或者在结构上,之后声明没有什么意义),可以只存储一个字符串,然后尝试调用函数。
如果对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()即可。