Variable scope with dictionaries [duplicate] - python

This question already has answers here:
Global dictionaries don't need keyword global to modify them? [duplicate]
(2 answers)
Closed 2 years ago.
This executes without error:
def myfunction():
global a_dict
a_dict['s'] = 'whatevs'
b_dict['s'] = 'lalala'
a_dict = b_dict
a_dict = {'s':[], 'm':[]}
b_dict = {'s':[], 'm':[]}
myfunction()
Why does this not throw an error without also adding global b_dict to the function - as I'm writing to both dictionaries?
It sure does if I comment out the global a_dict ("'a_dict' referenced before assignment") - as I would expect.

You only need global foo when you want to assign to the global name foo. You are not assigning to b_dict; you are assigning to one of its keys, equivalent to b_dict.__setitem__('s', 'lalala'). Both uses of b_dict treat it as a free variable, since there is no local variable named b_dict defined.
The value of a free variable is taken from the closest enclosing scope (in this case, the global scope) where it is defined.

The fact of declaring a variable as global in a function allows you to use a variable outside that function. If there is no variable b declared inside it, Python is going to assume it is a global variable declared before the function call.

Related

Global and local scope in 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.

globals() scope inside a function [duplicate]

This question already has answers here:
Short description of the scoping rules?
(9 answers)
Using global variables in a function
(25 answers)
Closed 5 years ago.
I have a question regarding globals() in python
My sample code
b=9
def a1():
'kkk'
a1()
print globals()
I got output b as global
Since b is global, I am expecting I can modify it anywhere
So I modified my code to
b=9
def a1():
'kkk'
b=100
a1()
print globals()
still my globals() says b as 100. Why b inside the function is taken as local value while my globals() says its global?
Note: If I add keyword global b inside the function, it get convert to global.
My question is why b was not getting modified inside the function while globals() declare b as global ?
Refer Python docs for more information. Copying the text in case URL doesn't work
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.
Though a bit surprising at first, a moment’s consideration explains this. On one hand, requiring global for assigned variables provides a bar against unintended side-effects. On the other hand, if global was required for all global references, you’d be using global all the time. You’d have to declare as global every reference to a built-in function or to a component of an imported module. This clutter would defeat the usefulness of the global declaration for identifying side-effects.
inside a function, unless you use the keyword global, it is not global variable that is modified. instead,a local variable is created and is destroyed as soon as it is out of scope
As your code b is a local variable in a1(), to use global variable, you should first say that to python and then use it, as follows:
b=9
def a1():
'kkk'
global b
b=100
a1()
print globals()

Scope of Python variables in this case - Difference between Enclosing and Local Variable

I am confused about the scope of python variables. How is this working
Consider the following example
i = 12
if i==12 :
str = "is equal"
else:
str = "NOT"
print str //Prints is equal - recognized the string str
The variable str is only in the scope of if statement and its scope is lost at the else statement. Since there is no hoisting in python. I am confused how this example works.I read this post and it states that Variables are scoped in the Following order
1-L (local variables are given preference)
2-E (Enclosing variables)
3-G (Global variables)
4-B (Builtin)
My question is what is the difference between Enclosing variable and local variable ?
The variable str is only in the scope of if statement and its scope is lost at the else statement.
Nope. Python is function scoped, not block scoped. Entering an if block doesn't create a new scope, so the str variable is still in scope for the print.
Enclosing variables are variables from functions enclosing a given function. They occur when you have closures:
def f():
x = 3
def g():
print x # enclosing variable
g()
Python doesn't have general block scope for, only function scope (with some additional weirdness for cases like class declarations). Any name assigned within a function will remain valid for the life of the function.
Enclosing scope applies when nesting function declarations, e.g.:
def foo(a):
def bar(b):
return a + b
return bar
So in this case, foo(1)(2) will create a bar whose enclosing scope is a foo call with a == 1, then call bar(2), which will see a as 1.
Enclosing scope also applies to lambda functions; they can read variables available in the scope surrounding the point where lambda was used, so for something like this:
val_to_key = {...} # Some dictionary mapping values to sort key values
mylist.sort(key=lambda x: val_to_key[x])
val_to_key is available; it wouldn't be in scope inside the sort function, but the lambda function binds the enclosing scope at declaration time and can therefore use val_to_key.

How to use shadowing with global variables?

I have notes from class but I am unsure what is actually happening.
Other than adding to confusion, what purpose does shadowing allow on to do? I thought the because globalString is a string type it cannot be modified? How do I access the original value? What is an instance of what in memory terms?
globalList = [1,2,3]
globalString = "global" # can't be modified because it's a string
def updateGlobalString():
global globalString # Does line this do anything?
globalString = "new"
print(globalString)
>>> "global"
updateGlobalString()
>>> "new"
def updateGlobalList():
globalList.append(4)
print(globalList)
>>> [1,2,3]
updateGlobalList()
print(globalList)
>>> [1,2,3,4]
If python Lists are mutable how does this example change the equation when compared to strings? And just to clarify, are any of these values actual Global?
Thank you.
Shadowing isn't a technique or a tool, it's something that is simply a consequence of Python's scoping rules.
I'm confused by your question about whether any of the variables are global. Anything declared at module level is global. The global keyword, when used in a non-global scope, allows you to rebind the name to a different object and have that rebinding take effect in the global scope too: otherwise you would simply be defining a new variable in the local scope (which would indeed be shadowing the original variable).
Global means that variable is going to occur in the global space. So that 1st function deletes the old string in global namespace and replaces it with a new one. However, a list is mutable and as a direct result can be changed outside of the global scope.

UnboundLocalError: local variable 'url_request' referenced before assignment [duplicate]

This question already has answers here:
Using global variables in a function
(25 answers)
Closed 8 years ago.
Think I'm going nuts here.
url_request = 0
def somefunction():
url_request+=1
if __name__ =='__main__':
somefunction()
Gives me the UnboundLocalError. What important concept am I missing here?
You are assigning to a global variable, which means you need to mark it as a global:
def somefunction():
global url_request
url_request+=1
When you assign to a variable in a local scope, it is assumed to be a local variable unless you use a global statement to tell python otherwise first.
For Python 2.7 we have to types of variables: global, local. Each function create it's own local scope for variables.
From local scope you can read without any restrictions. You can also call global object methods, so you can modify variable from global. But you can't reassign value.
Look at this code:
requests = [1,2,3]
def modify():
requests.append(4)
def redeclare():
requests = [10,20,30]
modify()
print requests
# will give you [1,2,3,4]
redeclare()
print requests
# will give you [1,2,3,4]
What's going on? You can't reassign requests variable from local scope, so interpreter create for you other variable - in local scope for redeclare call context.
Regarding to your code... Firstly, you try to reassign variable from global scope. Why? url_request is int, int is immutable, so operation url_request+=1 doesn't change value, it should reassign new value to variable name. Secondly, you don't specify global identify for this variable. So only one option for interpreter - to assume url_request as local variable. But... You didn't declare it's value anywhere....
UnboundLocalError means that you try to perform operations with variable value without declaring it before. Hope this will help you to understand more about Python variables/names/scopes.

Categories

Resources