Python variable scope

I started learning python and am currently reading through a script written by someone else. I noticed that globals are scattered throughout the script (and I don't like that). Additionally, I also noticed that when I have code like this

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

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

    some_function()

      

although I am not passing foo to some_function (), some_function can still manipulate foo (??!). I don't really like it, although it is somewhat similar to Javascript (?) Closure. I would like to know if it is possible to stop some_function () from accessing foo if foo is not passed as a function argument? Or is this the preferred way in python ??! (I am using python 2.5 under ubuntu hardy at the moment)

+2


source to share


3 answers


This script has some really serious styling and organization issues - for example, if someone imports them, they need to somehow be told what they should set thescript.foo

to an instance Some_Object

before calling some_function

... yeurgh! -)

It's unfortunate that you need to learn Python from a poorly written script, but I'm not sure I understand your question. A variable scope in Python is locales (including arguments), non-local (for example, locales for surrounding functions, for nested functions), globals, built-in functions.

Is this what you want to stop accessing global variables? some_function.func_globals

is read-only, but you can create a new function with empty globals:

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

      



now the call f()

will throw an exception NameError: global name 'foo' is not defined

. You can set this back in a named module, some_function

or even do it systematically through a decorator, for example:

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

      

this guarantees an exception when thrown some_function

. I do not understand what benefit you expect from this. Maybe you can clarify ...?

+4


source


As far as I know, the only way to stop some_function

from accessing foo

is to exclude the variable foo

from scope some_function

, perhaps for example:

tmp = foo
del foo
some_function()
foo = tmp

      

Of course this will crash your (current) code as it foo

no longer exists in scope some_function

.

In Python, variables are searched locally, then up in scope to globally, and finally built-in modules are searched.



Another variant:

with some_object as foo:
    some_function()

      

But then you have to at least declare some_object.__exit__

, maybe some_object.__enter__

. The end result is that you control what foo

is in the area some_function

.

More explanation in the "with" clause here .

+2


source


In python, something foo

doesn't seem to be a value, it's a name. When you try to access it, python tries to find the value associated with it (like dereferencing a pointer). It does this by first looking at the local scope (function), then working its way up until it reaches the module scope (i.e. the Global), and finally inline until it finds something that matches name.

Something like this work:

def foo():
    bar()

def bar():
    pass

      

Although it bar

doesn't exist when you defined foo

, the function will work because you later defined bar

in the scope that includes foo

.

Likewise, it happens in the code you post, which foo

is what is the output Some_Object()

, not the definition of the function.

As Alex said, just because you can write code like this doesn't mean you should.

+1


source







All Articles