我正在查看以下代码:
def f():
print(x)
if __name__ == '__main__':
x = [1,2,3]
f()
令我惊讶的是。我本以为那是行不通的,因为我本想需要在x
的函数定义之前定义f
(否则,f
怎么知道x
指的是什么至?)。因此,我希望以下是应该起作用的唯一版本:
x = [1,2,3]
def f():
print(x)
if __name__ == '__main__':
#x = [1,2,3]
f()
尽管我显然错了。为什么?我应该弄错Python应该如何工作的哪一部分?
请注意,作为编码实践,我永远不会使用全局变量。它们很危险,不清楚。我个人总是将变量传递给函数(或类似的更清晰安全的函数)。只是出于好奇。
答案 0 :(得分:4)
为什么不起作用?创建函数时,它只是一个代码片段,直到调用它,它才被执行(有点懒惰的评估)。这就是Python与其他编译语言(例如C ++)之间的差异,这会引发undefined variable x
错误。
调用函数x
时,只需要变量f
存在。它将首先在局部范围内查看某个变量x,然后在全局范围内查看,因此这就是为什么它仍然起作用的原因,即使x是在函数之后定义的也是如此!
答案 1 :(得分:3)
要做需要在使用变量之前对其进行定义:
def f():
print(x)
if __name__ == '__main__':
x = [1,2,3] # definition
f() # use
如果您尝试过另一种方法:
def f():
print(x)
if __name__ == '__main__':
f() # use
x = [1,2,3] # definition
那是行不通的。
定义f
时,您没有使用x
。您只是在编写最终将使用x
的代码。该代码将在实际尝试使用x
变量时去寻找它,而不是在函数定义时去寻找。
答案 2 :(得分:2)
在第一个版本中,即:
def f():
print(x)
if __name__ == '__main__':
x = [1,2,3]
f()
由于x
块的封闭作用域,变量if
在作用域内,因为python没有块作用域x
在函数{{1 }}
与第二版相同:
f()
x = [1,2,3]
def f():
print(x)
if __name__ == '__main__':
f()
在全球范围内。因此,除非您在x
的定义中明确包含global x
,否则将无法访问,这不是一个好习惯。
请从官方documentation阅读以下摘录:
范围是Python程序的文本区域,其中的命名空间为 直接访问。这里的“直接访问”是指 对名称的不合格引用尝试在 命名空间。
尽管范围是静态确定的,但它们是动态使用的。 在执行期间的任何时间,至少有三个嵌套作用域 可以直接访问其名称空间的
最先搜索的最内部作用域包含本地名称
从最接近的封闭范围开始搜索的任何封闭函数的范围都包含非本地范围,但也包含 非全局名称
倒数第二个范围包含当前模块的全局名称
最外面的作用域(最后搜索)是包含内置名称的命名空间