我已经开始学习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)
答案 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
尽管在定义bar
时foo
不存在,但该函数将起作用,因为您稍后在包含bar
的范围中定义了foo
。 / p>
在你发布的代码中发生了同样的事情,只是foo
是Some_Object()
的输出,而不是函数定义。
正如亚历克斯所说,你可以编写代码这样的事实并不意味着你应该。