Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Short description of the scoping rules?

What exactly are the Python scoping rules?

If I have some code:

code1 class Foo:    code2    def spam.....       code3       for code4..:        code5        x() 

Where is x found? Some possible choices include the list below:

  1. In the enclosing source file
  2. In the class namespace
  3. In the function definition
  4. In the for loop index variable
  5. Inside the for loop

Also there is the context during execution, when the function spam is passed somewhere else. And maybe lambda functions pass a bit differently?

There must be a simple reference or algorithm somewhere. It's a confusing world for intermediate Python programmers.

like image 964
Charles Merriam Avatar asked Nov 15 '08 01:11

Charles Merriam


People also ask

What are the scoping rules?

Scoping rules let you control the default records that your users see based on criteria that you select. You can set up scoping rules for different users in your Salesforce org so that they can focus on the records that matter to them. Users can switch the set of records they're seeing as needed.

What are the scoping rules for Python?

The Python scope concept is generally presented using a rule known as the LEGB rule. The letters in the acronym LEGB stand for Local, Enclosing, Global, and Built-in scopes. This summarizes not only the Python scope levels but also the sequence of steps that Python follows when resolving names in a program.

What is meant by scope rules of a language?

The scoping rules of a ProgrammingLanguage dictate how FreeVariables - symbol names which are found in the body of a scope (a function, macro, class, whatever) but not defined there - are resolved. Several different strategies exist: Disallowing them altogether.

What are function What are the scope rules functions?

Scope Rules of FunctionsEach function is a discrete block of code. The code of a function is private to that function and cannot be accessed by any statement in any other function except through a call to that function. (For instance, you cannot use goto to jump into the middle of another function.)


2 Answers

Actually, a concise rule for Python Scope resolution, from Learning Python, 3rd. Ed.. (These rules are specific to variable names, not attributes. If you reference it without a period, these rules apply.)

LEGB Rule

  • Local — Names assigned in any way within a function (def or lambda), and not declared global in that function

  • Enclosing-function — Names assigned in the local scope of any and all statically enclosing functions (def or lambda), from inner to outer

  • Global (module) — Names assigned at the top-level of a module file, or by executing a global statement in a def within the file

  • Built-in (Python) — Names preassigned in the built-in names module: open, range, SyntaxError, etc

So, in the case of

code1 class Foo:     code2     def spam():         code3         for code4:             code5             x() 

The for loop does not have its own namespace. In LEGB order, the scopes would be

  • L: Local in def spam (in code3, code4, and code5)
  • E: Any enclosing functions (if the whole example were in another def)
  • G: Were there any x declared globally in the module (in code1)?
  • B: Any builtin x in Python.

x will never be found in code2 (even in cases where you might expect it would, see Antti's answer or here).

like image 194
Rizwan Kassim Avatar answered Sep 28 '22 06:09

Rizwan Kassim


Essentially, the only thing in Python that introduces a new scope is a function definition. Classes are a bit of a special case in that anything defined directly in the body is placed in the class's namespace, but they are not directly accessible from within the methods (or nested classes) they contain.

In your example there are only 3 scopes where x will be searched in:

  • spam's scope - containing everything defined in code3 and code5 (as well as code4, your loop variable)

  • The global scope - containing everything defined in code1, as well as Foo (and whatever changes after it)

  • The builtins namespace. A bit of a special case - this contains the various Python builtin functions and types such as len() and str(). Generally this shouldn't be modified by any user code, so expect it to contain the standard functions and nothing else.

More scopes only appear when you introduce a nested function (or lambda) into the picture. These will behave pretty much as you'd expect however. The nested function can access everything in the local scope, as well as anything in the enclosing function's scope. eg.

def foo():     x=4     def bar():         print x  # Accesses x from foo's scope     bar()  # Prints 4     x=5     bar()  # Prints 5 

Restrictions:

Variables in scopes other than the local function's variables can be accessed, but can't be rebound to new parameters without further syntax. Instead, assignment will create a new local variable instead of affecting the variable in the parent scope. For example:

global_var1 = [] global_var2 = 1  def func():     # This is OK: It's just accessing, not rebinding     global_var1.append(4)       # This won't affect global_var2. Instead it creates a new variable     global_var2 = 2       local1 = 4     def embedded_func():         # Again, this doen't affect func's local1 variable.  It creates a          # new local variable also called local1 instead.         local1 = 5         print local1      embedded_func() # Prints 5     print local1    # Prints 4 

In order to actually modify the bindings of global variables from within a function scope, you need to specify that the variable is global with the global keyword. Eg:

global_var = 4 def change_global():     global global_var     global_var = global_var + 1 

Currently there is no way to do the same for variables in enclosing function scopes, but Python 3 introduces a new keyword, "nonlocal" which will act in a similar way to global, but for nested function scopes.

like image 34
Brian Avatar answered Sep 28 '22 06:09

Brian