2016-12-26 69 views
0

该脚本定义了main()中的变量,但该变量不可用于func(),该变量在main()内运行。这是为什么?子功能不可用的变量

#!/usr/bin/env python3 
# vars_in_func.py 
# Test script for variables within a function. 

def func(): 
    print(greeting) 

def main(): 
    greeting = "Hello world" 
    func() 

main() 

错误:

Traceback (most recent call last): 
    File "./vars_in_func.py", line 11, in <module> 
    main() 
    File "./vars_in_func.py", line 9, in main 
    func() 
    File "./vars_in_func.py", line 5, in func 
    print(greeting) 
NameError: name 'greeting' is not defined 

如果我转换脚本Python2,错误是一样的,只不过它说global name,而不是name

我假设我只是缺少一个关键概念。在学习Bash之后,我开始学习Python。

编辑:在阅读答案后,我意识到自己的错误:我仍然用Bash的方式来思考,其中函数或者在调用方的相同shell中运行(具有相同变量),或者调用者(继承变量)。

+2

阅读[范围规则](http://stackoverflow.com/questions/291978/short-description-of-scoping-rules) – trincot

+2

'func'不会在main()''里面运行。它只是由'main'调用。这并不意味着它会在'main'中看到局部变量。 – BrenBarn

回答

3
greeting = None 

def func(): 
    print(greeting) 

def main(): 
    global greeting 
    greeting = "Hello world" 
    func() 

main() 

在您的解决方案中,主函数中定义的问候语是局部变量,不能在主函数之外访问。这是它给你的错误的原因

+0

你能否澄清一下为什么你需要将问候标记为主要方法中的全局内容?忽略它会导致一些不好的魔咒。 – Irisshpunk

+0

'greeting'在函数main()中被标记为全局的,因为它在那里被修改。它在函数'func()中没有标记为全局的,因为它没有被修改*,只是被引用。明确? –

0

在python中,函数不能访问函数以外的任何变量,除非它的参数或被声明为global

这样应该可以解决这个问题:

greeting = None 

def func(): 
    print(greeting) 

def main(): 
    global greeting # Declaring as global means func() can access it 
    greeting = "Hello world" 
    func() 

main() 
+0

这不完全正确。一个函数可以访问全局变量,但是除非它们在函数的范围内被声明为'global',否则它不能赋值给它们。 – ekhumoro

2

我不知道很多关于蟒蛇,但在全球总体变量需要的主要范围,但该功能之前,定义你想使用它们。如果你不想做一个变量全局变量,你需要把变量作为参数传递给函数。

0

参见this post

在Python中,每个函数都有自己的作用域,所以你不能在函数'main'之外访问变量'greetings',因为它已经在这个函数中定义了。

1

关于python范围规则有很多答案,这里真的很重要。但是当我看到你的问题时,你的误解包含了完全不同的东西:定义函数和调用它的巨大差异。

LEGB规则很重要,但真正重要的是: “范围是静态确定的,它们动态地查找!。粗略地说,函数知道在哪里查找变量(编译时),但它不知道变量值(在调用函数之前)。

在你的情况下,你只需调用一个函数进入另一个函数的主体。当您调用函数时,调用者将控制权传递给被调用者(大致上,将其想象为源代码跳转到函数代码块的开头)。所以当你打电话给func你跳进func正文。该函数试图找到名字:printgreeting(这个过程被称为Name resolution),它看起来在local范围,然后在global范围(它被定义范围,不叫)终于在builtins。它仅在builtins中找到print。由于没有找到greeting名称,因此在您的案例中main调用func的地方会引发异常NameError(在检测到错误的位置发生异常)。当一个异常完全不被处理时,解释器终止程序的执行,或者返回到它的交互式主循环。无论哪种情况,它都会打印一个堆栈回溯,除非例外是SystemExit

希望它能为您澄清一些观点。

还有一个地方去寻找信息:The Python Language Reference: Execution model

P.S .:的global scope总是在那里被定义功能module(文件的代码)。了解这一点非常重要!