I am a beginner in python.
I am not understanding why about
assign after define global variable : valid
valid but define and assign global variable at once : not valid.
As for example:
def Test():
global a=15
Test()
print(a)
Is invalid while:
def Test():
global a
a=15
Test()
print(a)
Is valid
The global statement syntax is global <name> and just tells the interpreter that you are working with a variable from globals() instead of locals() for the current scope/frame. It really just tells Python where to grab the variable, and doesn't support assignment.
The global keyword tells your interpreter that a variable is a global one. Let's say you have this code:
a = 10
def p():
a = 20
print('This is a local:', a)
print("a is unchanged:", 10==a)
def q():
global a
a = 40
print('This is the global:', a)
print("a has changed:", 40==a)
Remember, the global only tells your interpreter that "There's this variable outside your local variables" when it is called inside functions. Therefore, you cannot assign a value to a variable that you are calling as global in one line.
I'm new to python as well, so I suppose I'll work this out with you! It looks like it indicates a syntax error at the = sign in line 2. It works in the second example because you declared the variable separately on a new indented line below global? So I'm guessing the first example won't work because the variable is declared along with global?
Related
I was just playing around with Python and I came across something interesting which I didn't quite understand. The code goes as follows:
a = 1
def function():
print(a)
function()
print(a)
Here, a is a global variable and I used it in my function and the result was:
1
1
I was able to use a global variable locally in my function without having to use global a in my function.
Then, I experimented further with this:
a = 1
def function():
a = a+1
print(a)
function()
print(a)
When I ran this code, an error showed up and it said that the local variable a was referenced before assignment. I don't understand how before it recognized that a was a global variable without global a
but now I need global a like this
a = 1
def function():
global a
a = a+1
print(a)
function()
print(a)
in order for this code to work. Can someone explain this discrepancy?
You can read the value from a global variable anytime, but the global keyword allows you to change its value.
This is because when you try and set the a variable in your function, by default it will create a new local function variable named a. In order to tell python you want to update the global variable instead, you need to use the global keyword.
When creating "=" ,a new variable inside a function python does not check if that variable is a global variable, it treats that new variable as a new local variable, and since you are assigning it to itself and it does not exist locally yet, it then triggers the error
When I compile this snippet with func1 I get an error about referencing output before assignment, which seems reasonable to me:
def func1():
output += 1
output = 0
func1()
print(output)
But when I compile this snippet with func2 I don't get an error, which seems unreasonable to me.
def func2():
output.append(1)
output = []
func2()
print(output)
Thoughts? Thanks in advance and sorry if this is a duplicate. I didn't didn't see this particular question addressed in similarly titled posts when researching.
The problem here is in how Python binds names to variables.
Any time you write an assignment in a function (something like a = b or a += b), Python will bind that name locally for the entire function scope. This means that any variables with that name declared outside the function are ignored.
For example:
a = 1 # This variable is ignored.
def foo():
print(a) # "a" hasn't been defined yet!
a = 2 # This causes "a" to bind to a local variable.
This will produce an UnboundLocalError at the print statement because Python sees that a is assigned to later in the function, and binds it locally, ignoring the variable you defined outside the function. Since a is only defined after the print statement, you get an error.
This can be very confusing because removing the a += 2 line will cause the print statement to work as expected!
The solution is to explicitly tell Python not to bind the name locally. This can be done with the global and nonlocal keywords, e.g.:
a = 1
def foo():
nonlocal a # or: global a
print(a)
a += 2
global tells Python to bind the name in the module's global scope, while nonlocal (introduced in Python 3) tells Python to bind to the enclosing scope (for example, if you define a function inside a function).
There's a nice explanation of this (with examples) in the documentation :-)
Once we understand these rules, we can see that your first example fails because you're trying to increment a variable that doesn't yet exist. output += 1 is equivalent to output = output + 1, which triggers local name binding.
On the other hand, your second example doesn't trigger the error because you're not assigning to output (you're mutating it instead), so it will bind to the global variable that you defined.
In Python, global variables when called in functions don't work all the same.
The data types (on a high level) in Python can be categorised into "mutable" and "immutable".
If you have have mutable datatypes like list then they can be both : accessed and modified in the function without referring them with a global keyword.
Eg:
l = []
def foo():
l.append(1) #works
foo()
print(l) # prints [1], so foo() changed the global list l.
But if you have immutable types like int or str then they can be accessed but not modified.
Eg:
someString = "abcdef"
def foo():
print(someString[2]) # prints "c"
someString += "l" # error as someString cannot be modified unless you include it in the function foo() with the global keyword as shown below.
But to modify a global variable of immutable types like str you have to include it first with the global keyword then you're free to use it like any local variable.
Eg:
someString = "abcdef"
def foo():
global someString # This now includes someString in foo() scope and is allowed to be modified.
print(someString[2]) # prints "c"
someString += "l" # works as expected
print(someString) # prints "abcdefl"
Thanks to Mark Tolonen for this valuable point. At the end, you cannot reassign a global variable without the global keyword, irrespective of whether the variable is mutable or immutable.
Eg:
someInt = 1
someStr = "abc"
someList = [1,2,3]
def foo():
someInt += 3 # error, local variable referenced before assignment.
someStr += "def" # error, local variable referenced before assignment.
someList += [4] # error, local variable referenced before assignment. Note that this is **not** the same as doing someList.append(4).
To make the above work, include them in the function via global keyword and use them as required.
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.
I cannot quite find a good description on how import works when importing your own files.
I was having trouble importing a file with a global variable and managed to get it to work when I put the global variable just before the files main function.
Can someone explain why it works this way?
A quick run down on how import actually works.
It did not work when I did this (pseudocode):
file1:
import file2
file2.main()
file2:
main():
glob_var = 0
def add():
global glob_var
glob_var += 1
add()
But worked if I put the variable first like this:
file1:
import file2
file2.main()
file2:
glob_var = 0
main():
def add():
global glob_var
glob_var += 1
add()
'main' is just a method. Variable inside a method is local by definition. Thats why 2nd way is working.
The reason it didn't work is because you are declaring the global variable inside of main. (you did miss the colon after definition of main which makes it confusing but looking at the indentation I suppose it's a definition). Global variables have to be defined outside the scope of any local function. This is a case of nested function definition.
You can do without global variables as well if that's what you are looking for. If however you want to use the variable defined in main inside a nested function then you can do the following:
In python 3 there is a way to get this thing done however using the nonlocal keyword
def main():
var = 10
def nested_fun():
nonlocal var
var = var + 1
As you see we do not need a global variable here.
Edit: In case of python 2 this does not work. However you can use a list in the main and modify that list inside nested function.
def main():
var = [10]
def nested_fun():
nonlocal var
var[0] = var[0] + 1
If I understand the question correctly, it's regarding the global variable and have nothing to do with importing.
If you want to define a global variable, it has to be defined in module level. The main function is not the global scope, that's why the first code does not work as expected. By moving the variable declaration outside of main, it would be defined in global scope, so the add method can access it using as a global variable.
I think we have to begin with what global statement means. From the docs:
It means that the listed identifiers are to be interpreted as globals.
The important point is it's only about interpretation, i.e. global does not create anything. This is the reason, why your first example does not work. You are trying to add +1 to something not existing. OTOH, global_var = 100 would work there and it would create a new global variable.
I keep getting an unbound local error with the following code in python:
xml=[]
global currentTok
currentTok=0
def demand(s):
if tokenObjects[currentTok+1].category==s:
currentTok+=1
return tokenObjects[currentTok]
else:
raise Exception("Incorrect type")
def compileExpression():
xml.append("<expression>")
xml.append(compileTerm(currentTok))
print currentTok
while currentTok<len(tokenObjects) and tokenObjects[currentTok].symbol in op:
xml.append(tokenObjects[currentTok].printTok())
currentTok+=1
print currentTok
xml.append(compileTerm(currentTok))
xml.append("</expression>")
def compileTerm():
string="<term>"
category=tokenObjects[currentTok].category
if category=="integerConstant" or category=="stringConstant" or category=="identifier":
string+=tokenObjects[currentTok].printTok()
currentTok+=1
string+="</term>"
return string
compileExpression()
print xml
The following is the exact error that I get:
UnboundLocalError: local variable 'currentTok' referenced before assignment.
This makes no sense to me as I clearly initialize currentTok as one of the first lines of my code, and I even labeled it as global just to be safe and make sure it was within the scope of all my methods.
You need to put the line global currentTok into your function, not the main module.
currentTok=0
def demand(s):
global currentTok
if tokenObjects[currentTok+1].category==s:
# etc.
The global keyword tells your function that it needs to look for that variable in the global scope.
You need to declare it global inside the function definition, not at the global scope.
Otherwise, the Python interpreter sees it used inside the function, assumes it to be a local variable, and then complains when the first thing that you do is reference it, rather than assign to it.