从外部函数访问变量

时间:2014-10-28 08:20:26

标签: python

我对Python很新,但在C ++方面有点经验,这就是下面代码示例让我感到困惑的原因。

def foo():
    y = x
    print y

x = 5
foo()

运行此代码将打印值5.如何在foo()中知道变量x的值? 上面的代码不会在C ++中运行,如果我们完成的话就会运行:

#include <iostream>

int x = 5;
void foo()
{
    std::cout << "x = " << x << std::endl;
}

int main()
{
    foo();
    return 0;
}

因为这里x是全局范围中的变量,它在foo()之前被声明(和定义)。 它是否在Python中工作,因为x被添加到全局符号表中?

感谢您的帮助!

4 个答案:

答案 0 :(得分:3)

从内部功能中可以看到全局范围内的所有内容。它必须是这样的:Python中没有区别于指向变量的名称和指向函数的名称,所以如果这不起作用,你甚至无法调用函数

但是如果你想修改x,你需要全局关键字。

为什么在函数之后定义变量时它起作用:Python在编译时没有尝试解析引用,它在调用函数时会这样做:因为python中的所有内容都是动态的,所以&#39;如果定义了变量,则无法提前告知。

答案 1 :(得分:3)

真正的区别在于变量查找在两种语言中是如何工作的。

在C ++中,代码是一次编译的。当编译器读取foo的代码时,它会看到x,并且还不知道该标识符的内容。它可以是任何类型的变量,也可以是函数,也可以是打字错误。如果它还没有看到x的定义 - 解释 x x是什么类型的东西,虽然不一定是它的实际 - 那么它将会立即报告错误。

当Python看到x时,它知道名称 - 即标识符 - 因为它匹配相应的令牌类型,而不是语言关键字。在Python中,一切都是一个对象,我们的意思是 - 包括函数。在编译时没有类型检查,所以我们不关心x是一个整数,还是一个函数,或者只是什么 - 所有这些东西都可以用同样的方式处理。 (是的,你可以打印函数 - 但它没有显示任何有用的东西,比如原始代码;它只是为你提供了一个存根,其中包含有关类型,名称和对象ID的一些基本信息)。实际上不能进行任何类型检查,因为Python的变量没有类型(甚至不是隐式类型,比如像Haskell这样的类型推断语言) - Python的有一个类型。 / p>

还没有有效性检查来查看x是否确实存在,因为再也没有一个 - 在Python中有一些方法可以动态创建名称(一般来说请不要)。

但是,可以在编译时进行足够的分析以确定x不是局部变量,因此Python生成的代码“查找名为x的全局变量并使用它” 。当foo实际运行时,以例外的形式发生任何结果错误。如果x实际上并不存在为全局,则会引发NameError;如果它存在,但相应的对象是错误的类型(通常print不可能,但可能例如+),它会引发TypeError,如果它是正确的类型但是值无效,它通常会引发ValueError或其子类型(例如,list中的无效数字索引将引发IndexError,这是ValueError的子类型。

答案 2 :(得分:2)

我希望您觉得此代码很有用。

def foo():
    y = x # y becames local while x ..is found as a global
    print "globals=", globals()
    print "locals=", locals()
    print y

x = 5 # here you declare variable x with global scope and with value 5
foo()

--------------------
$ python test.py
globals= {'__builtins__': <module '__builtin__' (built-in)>, '__file__': 'test.py', '__package__': None, 'x': 5, '__name__': '__main__', 'foo': <function foo at 0x7f0d4cbf05f0>, '__doc__': None}
locals= {'y': 5}
5

答案 3 :(得分:1)

AFAIK Python(就像Lua一样)将全局变量视为一旦定义它们就一直存在。因此,在定义函数并将x设置为5之后,它们都存在并且一直存在于Python中。调用foo()时,它将在全局和本地名称空间中搜索名为&#39; x&#39;的变量。然后它会找到一个值为5的打印件。