Why can't I set a global variable within a function?

Why can’t I define “grade = F” outside the function?

Here is my code:

grade = "F"
def grade_converter(gpa):
  if gpa>=4.0:
    grade = "A"
  elif gpa>=3.0:
    grade = "B"
  elif gpa>=2.0:
    grade = "C"
  elif gpa>=1.0:
    grade = "D"
  return grade

If my input is greater than or equal to 1.0, then the result will be okay. But, if my input is less than 1, there will be the error like:

Traceback (most recent call last):
File “script.py”, line 13, in
print(grade_converter(0.8))
File “script.py”, line 11, in grade_converter
return grade
UnboundLocalError: local variable ‘grade’ referenced before assignment

1 Like

Defining grade inside the function works well, but if I define grade before defining the function, I get a name error. Why?

Global variables can be accessed from within functions, but we cannot set them without explicitly naming them as global inside the function.

foo = 0
def bar():
  global foo
  foo += 1

That may have some bearing on your case.

4 Likes

Hi @husainritonga,

From what I’ve read about writing clean code and assigning values to global variables, the main reason (besides the fact that it results in an UnboundLocalError and breaks your code) not to set grade to “F” here is that there is no compelling reason to do so, and it makes the code just that slight bit more confusing to all who might have to read it subsequently. Whoever tries to rewrite your code later for whatever reason will have to ask “Why is the default grade “F”? Is there a reason for this?”

The only reason to do it in the first place is that it (potentially) saves one line of code (we’re overlooking the fact that it makes the code snippet non-functional). And that’s a reason, but not a compelling one.

Does it matter on 10 lines of code if there’s a moment’s hesitation on the part of whoever looks at your code later? On 10 lines, no. But multiply that out by function after function, line after line - you write a simple 1000-line program (okay, that’s not sooo simple, but you get what I’m saying), and if you’re careless about how the code is written after every step, suddenly you have 100 different places where anyone refactoring or otherwise dealing with your code has to stop and say “Why did the coder do this?”

They say that most coders/developers spend over half their time reading code rather than writing it. Sounds plausible to me.

So think of the generations to come who will need to calculate their grades using your function!

Have a good one, and happy coding everyone.

2 Likes

I know one way to change global variable inside a function is to use the keyword ‘global’ and define the variable you intend to use. Example in this case:
def grade_converter(gpa):
global grade

Doing it this way will return the grade value when gpa is below 1.0. But I too don’t understand why it gives error. grade is defined globally, so if no condition is met, it should access the value defined globally.
Maybe some experienced programmer here can answer this.

You are right but in his case, if no condition is met, then grade is never set and the function should use the globally defined grade, which it doesn’t in this case. And that’s confusing me.

I had that exact question : “Why is the default grade “F”? Is there a reason for this?”
Thanks for your answer, even I’m not totally sure I get it, at least It is a start.

Hi @digitalplayer39038,

The default grade is "F" in this exercise, because the if and elif blocks have previously handled all the other possibilities. If the grade is not "A", "B", "C", or "D", then "F" is the only possibility that remains.

Though the instructions do not ask you to do it this way, you could rewrite the function so that the default is "A", as follows:

 def grade_converter(gpa):
  if gpa < 1.0:
    grade = "F"
  elif gpa < 2.0:
    grade = "D"
  elif gpa < 3.0:
    grade = "C"
  elif gpa < 4.0:
    grade = "B"
  else:
    grade = "A"
  return grade

Link to exercise: Python: Control Flow: Else If Statements

Last edited on November 11, 2019 to provide a link to the exercise

dont know why but your answer is like using other planet’s language, what is foo, why there is +=1 , global is a syntax?,
sr but your answer alw confuse me.

It is a generic, or pseudo variable name. Note that it is defined in global scope (not inside the function).

That is a step that changes the value of foo inside the function.

Yes, it is Python syntax, and more importantly a necessary declaration inside a function if we are going to mutate a variable in global scope.

>>> foo = 0
>>> def bar():
	foo += 1

	
>>> bar()
Traceback (most recent call last):
  File "<pyshell#39>", line 1, in <module>
    bar()
  File "<pyshell#38>", line 2, in bar
    foo += 1
UnboundLocalError: local variable 'foo' referenced before assignment
>>> def bar():
	global foo
	foo += 1

	
>>> bar()
>>> foo
1
>>>