是否有可能在Python中转发声明一个函数?
是否有可能在Python中转发声明一个函数? 我想在声明之前使用我自己的cmp
函数对列表进行sorting。
print "\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])
我已经组织了我的代码,在调用之后放置了cmp_configs
方法的定义。 它失败,出现这个错误:
NameError: name 'cmp_configs' is not defined
在使用cmp_configs
方法之前,有没有办法“声明” cmp_configs
方法? 这将使我的代码看起来更清洁?
我想有些人会试图告诉我,我应该重新组织我的代码,使我没有这个问题。 但是,有些情况下,这可能是不可避免的,例如在执行某种forms的recursion时。 如果你不喜欢这个例子,假设我有一个真正需要转发声明一个函数的情况。
考虑一下在Python中向前声明一个函数是必要的:
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
已经被定义。
是唯一的解决scheme来重新组织的代码,总是把调用之前的定义?
如果你不想在使用它之前定义一个函数,并且之后定义它是不可能的,那么在其他模块中定义它呢?
从技术上讲,你仍然首先定义它,但它很干净。
你可以像下面这样创build一个recursion:
def foo(): bar() def bar(): foo()
Python的函数是匿名的,就像值是匿名的,但它们可以绑定到一个名字。
在上面的代码中, foo()
不会调用名称为foo的函数,它会调用恰好在调用时绑定到名称foo
的函数。 有可能在其他地方重新定义foo
,然后bar
会调用新的函数。
你的问题不能解决,因为它就像要求得到一个尚未宣布的variables。
如果您通过以下方式启动您的脚本:
if __name__=="__main__": main()
那么你可能不必担心“前向声明”这样的事情。 你看,解释器会加载你所有的函数,然后开始你的main()函数。 当然,确保你所有的import都是正确的;-)
想想吧,我从来没有听说过python中的“前向声明”这样的东西…但是再一次,我可能是错的;-)
你可以做的是把调用包装成一个自己的函数。
以便
foo() def foo(): print "Hi!"
会打破,但是
def bar(): foo() def foo(): print "Hi!" bar()
将正常工作。
Python
一般规则并不是应该在代码中定义更高的function(如在Pascal
),而是应该在使用之前定义它。
希望有所帮助。
如果对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中转发声明一个函数。
想象一下,你是Python解释器。 当你到达线路
print "\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])
要么你知道cmp_configs是什么,或者你不知道。 为了继续,你必须知道cmp_configs。 如果有recursion没有关系。
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.
你可以认为一个函数体是另一个脚本,一旦你调用函数就会被解释。
有时候,一个algorithm最容易理解,从整体结构开始,深入细节。
你可以这样做,没有前向声明:
def main(): make_omelet() eat() def make_omelet(): break_eggs() whisk() fry() def break_eggs(): for egg in carton: break(egg) # ... main()
我很抱歉重振这个主题,但是这里没有讨论可能适用的策略。
使用reflection可以做类似于前向声明的事情。 例如让我们说你有一段代码,看起来像这样:
# 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中,由于上面讨论的原因,语句globals()[function_name]()
与foo()
相同,因为python必须在调用每个函数之前查找每个函数。 如果使用timeit
模块来查看这两个语句如何比较,则它们具有完全相同的计算成本。
当然这里的例子是无用的,但是如果有一个需要执行一个函数的复杂结构,但是必须在之前声明(或者在结构上它没有什么意义),那么可以存储一个string尝试稍后调用该函数。
你不能在Python中转发声明一个函数。 如果你在定义函数之前执行了逻辑,反正你可能会遇到问题。 把你的行为放在脚本末尾的if __name__ == '__main__'
(通过执行一个名字为“main”的函数,如果它不重要),你的代码将更加模块化,你就可以使用它作为一个模块,如果你需要的话。
另外,用一个生成器expression式来replace列表理解(例如,在已sorting的(mylist,cmp = cmp_configs))中打印“\ n”.join(str(bla)
另外,不要使用不推荐使用的cmp。 使用“键”并提供一个小于function。
“只是重新组织我的代码,使我没有这个问题。” 正确。 容易做到。 始终有效。
您可以在参考之前始终提供该function。
“但是,有些情况下,这可能是不可避免的,例如,当实施某种forms的recursion”
看不到这是甚至是远程可能的。 请提供一个在使用前无法定义function的例子。
现在等一下。 当你的模块到达你的例子中的print语句之前,在定义cmp_configs
之前,你期望它做什么?
如果你使用print来发布一个问题,实际上是想expression如下的东西:
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
variables。
[编辑 – 这下一部分结果是不正确的,因为默认参数值将在编译函数时得到分配,即使您稍后更改cmp_configs的值,将使用该值。
幸运的是,Python是如此typescmp_configs
,不关心你定义为cmp_configs
,所以你可以只用这个语句:
cmp_configs = None
编译器会很高兴。 只要确保在调用fn
之前声明真正的cmp_configs
。
一种方法是创build一个处理函数。 尽早定义处理程序,并将处理程序放在您需要调用的所有方法的下面。
然后,当你调用处理函数来调用你的函数时,它们将始终可用。
处理程序可以采用参数nameOfMethodToCall
。 然后使用一堆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)