代码之家  ›  专栏  ›  技术社区  ›  Jeffrey04 George

python变量范围

  •  2
  • Jeffrey04 George  · 技术社区  · 15 年前

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

    def some_function():
        foo.some_method()
        # some other code
    
    if __name__ == '__main__' :
        foo = Some_Object()
    
        some_function()
    

    尽管我没有将foo传递到某个_function(),但是一些_函数仍然能够操作foo(??!).I不太喜欢这个,尽管它有点类似于javascript闭包(?).I想知道如果没有将foo作为函数参数传入,是否可以阻止某些_Function()访问foo?或者这是Python中的首选方法??!(我现在使用的是UbuntuHardy下的python 2.5)

    3 回复  |  直到 15 年前
        1
  •  4
  •   Alex Martelli    15 年前

    这个脚本在风格和组织上确实存在严重的问题——例如,如果有人导入它,他们必须以某种方式预测他们必须设置的事实。 thescript.foo 到的一个实例 Some_Object 打电话之前 some_function …耶!-)

    不幸的是,你不得不从一个写得不好的脚本中学习Python,但我不确定我是否理解你的问题。python中的变量范围是局部变量(包括参数)、非局部变量(即周围函数的局部变量,对于嵌套函数)、全局变量、内置变量。

    您要停止访问Globals吗? some_function.func_globals 是只读的,但可以使用空全局值生成新函数:

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

    正在呼叫 f() 会有例外 NameError: global name 'foo' is not defined . 您可以在模块中用名称将其设置回 某些函数 或者甚至通过装饰器系统地进行,例如:

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

    这将保证在任何时候发生异常 某些函数 被称为。不过,我不清楚你希望从中得到什么好处。也许你能澄清…?

        2
  •  2
  •   Mark Rushakoff    15 年前

    据我所知,唯一的方法就是 some_function 从访问 foo 是为了消除 变量从 某些函数 的作用域,可能类似于:

    tmp = foo
    del foo
    some_function()
    foo = tmp
    

    当然,这会使您的(当前)代码崩溃,因为 不存在于 某些函数 不再。

    在python中,变量在本地搜索,然后在作用域中搜索,直到全局搜索,最后搜索内置的。

    另一选择 能够 铍:

    with some_object as foo:
        some_function()
    

    不过,你至少得申报 some_object.__exit__ ,也许 some_object.__enter__ 也。最终结果是你控制了 属于 某些函数 .

    关于“with”语句的更多解释 here .

        3
  •  1
  •   John Fouhy    15 年前

    在巨蟒中 foo 不是值,而是 名称 . 当您尝试访问它时,python会尝试查找与之关联的值(比如取消对指针的引用)。它首先查找本地作用域(函数),然后向外扩展,直到到达模块作用域(即全局作用域),最后嵌入,直到找到与名称匹配的内容。

    这使得类似这样的工作:

    def foo():
        bar()
    
    def bar():
        pass
    

    尽管事实上 bar 定义时不存在 ,函数将起作用,因为您稍后定义了 酒吧 在封闭的范围内 .

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

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