Global and local scope in python - python

Just a beginner question about local and global scope in python
X = 100
#is X a global variable?.We defined it outside the function scope
def foo():
print(X)
return X
#it prints 100 and even returns it
def foo():
X = X + 10
#local error
#UnboundLocalError: local variable 'X' referenced before assignment
def foo():
global X
# if X is a global variable why specify again?
X = X + 10
return X

To modify global copy of a variable you need the to use the global keyword, but you don't need global if you are only accessing that.

from the python website:
In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a value anywhere within the function’s body, it’s assumed to be a local unless explicitly declared as global.
this means that you can access a global variable inside a function without a global keyword. if you want to change it though, you must use the global keyword beforehand.

global and nonlocal are very strange things when I was a beginner.
Just think about it: why do we need them in Python?
It is because we don't need var, let and such similar things to declare variables.
Think about Javascript, it is dynamic script language too and very alike to python, but it needs var or let or const to declare variables.
The most important thing of declaring variables is to determine scope.
So, in Python, our variables have implicit default scope: current scope where they are defined, and if we want to change scope of some variables, we need use global or nonlocal explicitly .
All names on the left side of = mean to define variables.
Before executing code of some certain scope, Python will pre-compute all local variables, which are those on the left side of =. This is why you got UnboundLocalError: local variable 'X' referenced before assignment in:
def foo():
X = X + 10
So, if we look up those names not in defined current scope, just
follow the rules of scope chain: up, up, up and until built_in.
Remember: scope of any name on the left side of = is default current scope, and you have to assign it(bind something to it) before referring it.

Related

Why Python "global" statement is always evaluated, even under conditional statement that is not met?

I don't know how to explain the case, just try for yourself:
x = 7
def f():
if False:
global x
print("global")
x += 1
f()
print(x)
In my opinion, the above code should result in "UnboundLocalError: local variable 'x' referenced before assignment", but instead it not only works, but it changes the global variable 'x'.
A function gets a local namespace every time it is called. Python needs a way to know which variables are defined in that namespace or a containing namespace. Instead of requiring that all local variables be declared local, python's rule is that any variable that is assigned in a function is local to that function. It figures this out at compile time.
The global keyword does the opposite. It tells python that in this single function, assignment to the "global" variable is really an assignment in the enclosing namespace. Like local variables, this is figured out when the function is compiled. Because of compilation issues, python requires that the global be declared before the first reference to the variable. This is a compile thing, not a runtime thing, so its okay for it to be in a block that isn't ever really run.

How to set an arbitrary variable as global in Python?

How do you dynamically set variables as global in Python 3 functions?
Something like this:
def func1(i):
global i
#Some operation on i
How would I get the global variable to set whatever pre-existing variable is passed into the function? Such that:
func1(foo)
Would preform the operation on the variable foo globally rather than creating a new global variable called i?
If I got it right, your problem is:
I've bound a name to some object at module level; now I want to write a function that changes the binding of that global name to another object passed as an argument to the function.
In Python global names can be referenced inside a function (provided that you don't bind another object to the same name), but to change their binding you must first declare those names as global. The reason is simple: by default all names bound inside a function have function scope.
GLOBAL_NAME = 12
ANOTHER_GLOBAL_NAME = 50
def func(value):
global GLOBAL_NAME
GLOBAL_NAME = value
print(GLOBAL_NAME, ANOTHER_GLOBAL_NAME)
When you call func(33), GLOBAL_NAME will be bound to the object 33. ANOTHER_GLOBAL_NAME is just a reference to a global name; since that name is not bound inside the function, Python look for that name in the global scope.
For further insights on Python scope enclosing you can refer to the Python documentation on the global statement, to PEP-0227 and to PEP-3104.

How to create a global variable if it doesn't exist in Python?

I want to define a Python function doing:
1. Check if a variable already exist.
2. If not, create it as a global variable (because I want to use it outside the function).
def foo():
try:
x
except NameError:
global x
x = 1
else:
pass
foo()
print(x)
Then there is an error:
SyntaxError: name 'x' is used prior to global declaration
How to solve this? Thank you :)
Something like this could work.
def foo():
if not('x' in locals()):
global x
x = 1
foo()
print(x)
just check if the x variable exists.
you could also check if a variable is declared as global
if not('x' in globals()):
Just declaring a variable as global at the top of your function won't create it - so this form works:
def foo():
global x
try:
x
except NameError:
x = 1
The key thing to understand here is that when Python compiles a function, it "bakes" each variable inside the function as either a local, nonlocal, or a global (or builtin) variable - any access to that variable will have either one or the other relevant bytecode. The "global" declaration thus affects the whole function, regardless of were it is - and since tryig to access a variable before the global statement would look ambiguous, the error you saw is forced.
But since you are at it - are you sure you want to do it?
global variables are good for having values that can be shared in functions in a module - but then, even if they are to be initialized in the call to an specific function, they should be declared in the module body, and properly documented. If you can't have the final value at module load time, just assign it to None.

Static/Dynamically Scoped,Typed,Binding

I am asking this just to clarify if i am thinking right.
Statically/Dynamically typed
A language is statically typed if the type of a variable is known at compile time. This in practice means that you as the programmer must specify what type each variable is. Example: Java, C, C++.
A language is dynamically typed if the type of a variable is interpreted at runtime. This means that you as a programmer can write a little quicker because you do not have to specify type everytime. Example: Perl
Static/Dynamic Binding-which the following link clearly explains the difference
Static Binding and Dynamic Binding
The main thing that i want to ask starts from here.
I know the difference between Static Scoping and Dynamic Scoping.
However as i was going through stack overflow people said that C++ and Python are Statically Scoped.
In c++ if i type
int void main(){
cout<<i;
int i=15;
}
int i=10;
It works(even in java).However its python equivalent
def foo():
print(x)
x=10
x='global'
foo()
Gives an error.
The scope is static in Python as well as in C++. The difference between those languages is related to rules that define start and end of the scope of names.
In C++ the variable i is considered as global before the local definition int i=15;.
In Python:
What are the rules for local and global variables in Python?:
If a variable is assigned a value anywhere within the function’s body,
it’s assumed to be a local unless explicitly declared as global.
Naming and binding:
When a name is used in a code block, it is resolved using the nearest
enclosing scope.
So, since the variable x is assined inside foo() it is assumed to be a local variable starting from the beginning of the function foo().
It is possible to treat x within entire function block as global using the global keyword:
def foo():
global x # name 'x' refers to the global variable
print(x) # print global 'x'
x=10 # assign global variable
x='global'
foo() # print 'global'
foo() # print '10'
Actually it is possible to access the global variable x even if you want to have a local name x in the same function using globals() build-it function:
def foo(): # name 'x' refers to the local variable
print(globals()['x']) # access the global name 'x'
x=10 # assign local variable
print(x) # print local 'x'
x='global'
foo()

Confusion about Python variable scope

I came across some code which kind of puzzled me. Here's a minimal example which shows this:
# of course, the ... are not part of the actual code
some_var = {"key1":"value1" ... "keyN":"valueN"}
def some_func():
v = some_var["key1"]
The code works, but the fact that I can access some_var directly confuses me. The last time I had to write some Python code, I remember having to write some_func like this:
def some_func():
global some_var
v = some_var["key1"]
I am using Python 2.7.1 on a Windows 7 PC. Did something change in the 2.7 release that allows for this?
No, you just can't reassign some_var in a local scope. Consider the following:
some_var = {}
def some_func():
# some_var[5] = 6
some_var = {1:2}
some_var[3] = 4
some_func()
print (repr(some_var)) # {}
You'll see the assignment in some_func actually creates a local variable which shadows the global one. Therefore, uncommenting the line would result in an UnboundLocalError - you can't access variables before they're defined.
There's a difference between using (e.g. calling or using in an expression) a name from an outer scope and assigning it (and there's a difference between assigning a bare variable and assigning a member of an object pointed to by a variable - x.y = ... and x[...] = ... count as method calls!).
You only need to declare that a variable is from an outer scope if you're re-assigning it. In Python 2, you can only do that with global variables (via global var), in Python 3 you can do it for abritarily nested scopes (e.g. closures) using nonlocal var.
Using a nonlocal variable as in you example doesn't require global. It does, however, as soon as you assign the variable (with the aforementioned definition of assignment) anywhere within that scope - so add a line some_var = ... after the line where you're using it and you'll get an UnboundLocalError. Refer to the documentation for the nitty gritty details.
You only have to use global if you want to assign a new value to that variable.
Nested scope was introduced in Python 2.1 (and enabled by default in Python 2.2) (emphasis mine):
Put simply, when a given variable name is not assigned a value within a function (by an assignment, or the def, class, or import statements), references to the variable will be looked up in the local namespace of the enclosing scope. A more detailed explanation of the rules, and a dissection of the implementation, can be found in the PEP.
You only need to use global if you intend to assign to the variable, for reading the variable this is not necessary. This difference is not arbitrary, though it may seem like it at first glance.
When reading a value the interpreter can just look for a local variable named some_var, if it cannot find it then it looks for a global variable of that name. These are simple and straight forward semantics.
When assigning values to a variable the interpreter needs to know whether you intend to assign to a local variable some_var or a global variable. The interpreter assumes that some_var = 2 when called within a function is assigning to a local variable, this makes sense since this is the most common case. For the relatively rare times when you want to assign to a global variable from within a function then you use the global modifier global some_var = 2.
It depends on the usage of the variable in the function
Python variable scope error
Assigning a value to a name makes the name local, unless the name is explicitly declared global.
a = 12
def foo():
a = 42
print a # uses local
foo()
>>> 42
def foo():
global a
a = 42
foo()
print a
>>> 42
If a name is not assigned to, it is global.
a = 12
def foo():
print a # uses global
foo()
>>> 12
In short, you only have to explicitly declare a name global if you will be assigning to it. If you are just reading from it, you can use it at will. However, if you ever assign to the variable, it will be considered local in that function unless you declared it global.
b = 5
def foo():
print b
b = 7
foo()
>>> ???
Since b is assigned to in foo() and not declared global, Python decides at compile time that b is a local name. Therefore b is a local name throughout the whole function, including at the print statement before the assignment.
Therefore the print statement gives you an error, because the local name b has not been defined!

Categories

Resources