Reputation: 21
I'm new to programming so this is probably a silly question!
I'm trying to write a function that takes a list of letter grades and returns a Boolean true or false depending on whether it is a passing grade
## Calculate total units passed
def unitPassed(letterGrade):
if letterGrade == 'N':
passed = False
else:
if letterGrade == 'NCN':
passed = False
else:
if letterGrade == 'WN':
passed = False
else:
True
return passed
unitsPassed = map(unitPassed,courseGradeLetter)
I've attempted to do this by creating a function that tests if a grade is a passing grade, and then map this over a list of grade.
The problem is that I get the following error for a list that contains more than one element:
local variable 'passed' referenced before assignment
If I try it with a list containing one element I get the correct result.
Any ideas why this is?
Thanks.
--
Thanks everyone, your answers have helped me a lot!
Upvotes: 1
Views: 2642
Reputation: 77942
Some have already pointed your error and posted the most pythonic solutions, but anyway - here's another code review, but this time a step by step one:
First point: learn to use elif
instead of nesting if
clauses in else
clauses:
def unitPassed(letterGrade):
if letterGrade == 'N':
passed = False
elif letterGrade == 'NCN':
passed = False
elif letterGrade == 'WN':
passed = False
else:
passed = True
return passed
As you can see this is already more readable.
Second point: in Python we favor "early returns" - ie, in this kind of tests, instead of setting a variable in all branches and returning it at the end, we return directly (which avoids elif
/else
chains etc):
def unitPassed(letterGrade):
if letterGrade == 'N':
return False
if letterGrade == 'NCN':
return False
if letterGrade == 'WN':
return False
return True
Which makes the code even more straightforward.
And of course the last refactoring is to avoid the multiple tests when possible, as posted by Dadep and digitake (but using a tuple instead of a list because we dont need the overhead of a list here):
def unitPassed(letterGrade):
return letterGrade not in ("N", "NCN", "WN")
Also, you are using map()
in your code snippet but while map()
is still perfectly valid and appropriate, the more idiomatic (and marginally faster) version here would be a list comprehension:
passed = [unitPassed(letter) for letter in courseGradeLetter]
And since unitPassed
is now basically a simple short expression, you can just inline it (unless of course you need this function elsewhere):
passed = [letter not in ('N', 'NCN', 'NWN') for letter in courseGradeLetter]
Upvotes: 4
Reputation: 459
The error is in the 3rd else statement, i.e. in line 13.
Change True
to passed = True
Also, you can make your function clean,
def unitPassed(letterGrade):
if letterGrade == 'N':
passed = False
elif letterGrade == 'NCN':
passed = False
elif letterGrade == 'WN':
passed = False
else:
passed = True
return passed
Upvotes: 0
Reputation: 856
how about this
def unitPassed(letterGrade):
return letterGrade not in ['N', 'NCN', 'WN']
unitsPassed = map(unitPassed,courseGradeLetter)
Upvotes: 2
Reputation: 2788
you can redefine your function as :
>>> def unitPassed(letterGrade):
... GP=['N', 'NCN', 'WN']
... if letterGrade in GP:
... return False
... return True
...
>>> letterGrade='DE'
>>> unitPassed(letterGrade)
True
>>> letterGrade='NCN'
>>> unitPassed(letterGrade)
False
Upvotes: 0