python变量范围

时间:2009-08-27 02:41:31

标签: python

我已经开始学习python,目前正在阅读其他人编写的脚本。我注意到整个脚本遍布全局(我不喜欢它)。除此之外,我还注意到当我有这样的代码时

def some_function():
    foo.some_method()
    # some other code

if __name__ == '__main__' :
    foo = Some_Object()

    some_function()

即使我没有将foo传入some_function(),但some_function仍然可以操作foo(??!)。虽然它有点类似于Javascript闭包(?),但我不太喜欢这个。我想知道如果foo没有作为函数参数传入,是否可以阻止some_function()访​​问foo?或者这是python中的首选方式??! (目前我在ubuntu下使用python 2.5)

3 个答案:

答案 0 :(得分:4)

该脚本在样式和组织方面存在严重问题 - 例如,如果有人导入它,他们必须以某种方式认为他们必须在调用之前将thescript.foo设置为Some_Object的实例。 some_function ...是的! - )

不幸的是,您必须从编写糟糕的脚本中学习Python,但我不确定我理解您的问题。 Python中的变量范围是locals(包括参数),nonlocals(即周围函数的本地,嵌套函数),globals,builtins。

您想要停止访问全局变量吗? some_function.func_globals是只读的,但您可以使用空的全局变量创建一个新函数:

import new
f=new.function(some_function.func_code, {})

现在调用f()会发出异常NameError: global name 'foo' is not defined。您可以在模块中将其设置为名称some_function,或者甚至通过装饰器系统地进行设置,例如:

def noglobal(f):
    return new.function(f.func_code, {})
...
@noglobal
def some_function(): ...

这将保证在调用some_function时发生异常。不过,我不清楚你期望从中得到什么好处。也许你可以澄清......?

答案 1 :(得分:2)

据我所知,阻止some_function访问foo的唯一方法是从foo的范围中删除some_function变量,可能如下: / p>

tmp = foo
del foo
some_function()
foo = tmp

当然,这会导致您的(当前)代码崩溃,因为foo不再存在some_function

在Python中,变量在本地搜索,然后在范围内向上搜索直到全局,最后搜索内置函数。

另一个选项可以

with some_object as foo:
    some_function()

但是,你必须至少声明some_object.__exit__,也许some_object.__enter__。最终结果是您可以控制foo范围内的some_function

关于“with”声明here的更多解释。

答案 2 :(得分:1)

在python中,foo之类的东西不是值,它是名称。当您尝试访问它时,python尝试查找与其关联的值(如解除引用指针)。它通过首先查看本地范围(函数),然后向外工作直到它到达模块范围(即全局),最后是内置函数,直到找到与名称匹配的内容为止。

这就是这样的工作:

def foo():
    bar()

def bar():
    pass

尽管在定义barfoo不存在,但该函数将起作用,因为您稍后在包含bar的范围中定义了foo。 / p>

在你发布的代码中发生了同样的事情,只是fooSome_Object()的输出,而不是函数定义。

正如亚历克斯所说,你可以编写代码这样的事实并不意味着你应该