至少在我看来,foo
会在函数foo
中为def
知道foo
是完全出乎意料的。这里到底发生了什么?
>>> def foo(x):
... print "wow"
... print globals().get('foo', 'sorry')
... return foo
...
>>> f = foo(3)
wow
<function foo at 0x10135f8c0>
>>> f
<function foo at 0x10135f8c0>
这是python惰性评估的某种影响吗?它先构建函数代码,然后将其放入
globals
,但是随后在调用它时实际上构建函数。哇...这是什么形式的python魔术?当然,这简化了递归操作……这可能是语言中的原因……
>>> def bar(x):
... return bar(x)
...
>>> bar(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in bar
File "<stdin>", line 2, in bar
File "<stdin>", line 2, in bar
...snip...
File "<stdin>", line 2, in bar
File "<stdin>", line 2, in bar
RuntimeError: maximum recursion depth exceeded
最佳答案
没有什么真正的神秘。
我认为这有两个方面,您正在对该函数主体进行后期评估。
更新:我对解释定义步骤之后发生的情况进行了解释-看起来函数代码在调用之前确实发生了某些事情。在这方面,沃利的答案比我的要好。
通过#1-找到def foo(x)并在模块的命名空间上进行设置。可能还会添加功能参数。
仅此而已,您无需深入研究代码。
更新:实际上,我不确定在调用之前是否以某种方式处理了代码。查看foo.func_code内部,在调用之前和之后都没有太大区别。
另外,如果您遇到语法错误(如括号嵌套或空格问题),甚至在调用该函数之前就出现了,因此在调用之前会先进行一些处理。最终请参阅我的代码。
我猜想代码已经解析了,但是任何变量解析都会推迟到实际执行为止。
传递#2-您调用foo(x),找到并调用了它。
该函数的代码是第一次执行。
当您点击globals()[“ foo”]时,它将获取存储在#1中的现有引用。
当您运行coverage.py或类似内容时,您还可以看到一些有关此行为的提示。导入时,模块中的所有外部定义都标记为已覆盖。
但是实际的代码仅在您调用它时被覆盖。
另一种思考的方式是,您需要先通过命名空间来设置引用,然后再继续。否则,在下面的代码中,foo将找不到bar。
这是我用来区分执行错误与语法错误的一些代码...
def foo(x):
"""comment/uncomment to see behavior"""
pass
# return bar(x) #this works
return bar2(x) #call time error
# return bar(x) bad whitespace #IndentationError, nothing runs
print "foo defined"
def bar(x):
return x*2
print "calling foo#1"
try:
print foo(3)
except Exception, e:
print e
#let's make it so there is a bar2...
bar2 = bar
print "calling foo#2"
try:
print foo(6)
except Exception, e:
print e