-1

I must modify the function gp so it will handle + and - grades by adding or subtracting 0.3 points. For example, a B + is worth 3.3 points, and a C- is 1.7 points.

Example.

>>> gp('A-')
3.7

>>>gp('B+')
3.3

The suggestion is I could just add a bunch of elif clauses to test each grade separately, but a similar design is to use a call to s.startswith to figure out the value of the letter grade, then use s.endswith to see if you should add or subtract 0.3 points.

So far this is what I have.

def gp(s):
       A = 4
       return A
       B = 3
       return B
       C = 2
       return C
       D = 1
       return D
       F = 0
       return f
tobias_k
  • 81,265
  • 12
  • 120
  • 179
Mdot
  • 13
  • 3

5 Answers5

3

Instead of a series of if/elif statements, you can store the numeric values for the grades and the suffixes in dictionaries. Also, you do not have to use startswith or endswith, you could just use s[0] and s[1] to get the first or second character in the string, after checking the length. You can also use s[1:] to get everything starting at the 1th position, even if it's empty.

grades = {'A': 4, 'B': 3, 'C': 2, 'D': 1, 'F': 0}
signs = {'+': 0.3, '-': -0.3, '': 0}
def gp(s):
    return grades[s[0]] + signs[s[1:]]

>>> gp("A+")
4.3
>>> gp("C-")
1.7
>>> gp("F")
0
tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • Isn't `s[1]` enough instead of `s[1:]`? Btw was about to post the same answer. :) – Austin Jun 01 '18 at 15:43
  • 2
    @Austin It is, but `s[1]` will fail without an additional check if no `+` or `-` is provided, whereas `s[1:]` will just return `''`. – tobias_k Jun 01 '18 at 15:43
2

There are several problems with the gp function.

While it is possible to enumerate them, I suggest you read the following resources:

When you're ready, I strongly recommend you use dictionaries to store your mappings. Here's an example:

grade_dict = dict(zip('ABCDF', (4, 3, 2, 1, 0)))
sign_dict = dict(zip('-+', (-0.3, 0.3)))

def gp(s):

    grade, *sign = s

    if sign:
        return grade_dict[grade] + sign_dict[sign[0]]
    else:
        return grade_dict[grade]

res = gp('A-')  # 3.7

Edit: My schooling didn't involve GPA, so I didnt't catch this. If you need to cap at 4.0, you can use this modification:

def gp(s):

    grade, *sign = s

    if sign:
        res = grade_dict[grade] + sign_dict[sign[0]]
    else:
        res = grade_dict[grade]

    return max(res, 4.0)
jpp
  • 159,742
  • 34
  • 281
  • 339
1

My suggestion would be to use a dictionary for how many points each specific grade would get. Using a dictionary is somewhat like the Python equivalent for a switch statement and is generally consider more idiomatic than a long if/elif/else chain. (My answer is assuming you're using the standard 4.0 GPA calculation scale. If not, this can obviously be changed to suite your needs.)

grade_to_points = {
    'A+':   4.0,
    'A':    4.0,
    'A-':   3.7,
    'B+':   3.3,
    'B':    3.0,
    ...
}

def gp(grade):
    points = grade_to_points.get(grade)
    if points is None:
        raise ValueError('{:r} is not a valid grade!'.format(grade))
Christian Dean
  • 22,138
  • 7
  • 54
  • 87
0

You should use dictionnaries

def function(grade)
  dict = {'A':4, 'B':3, 'C':2, 'D':1, 'F':0}
  if grade[1] == '+':
    return dict[grade[0]]+0.3
  elif grade[1] == '-':
    return dict[grade[0]] - 0.3

Then add or substract 0.3 depending on the sign

0

Another dictionary (hash) approach.

def gp(s):
    gradhash = {
        "A+": 4.0 + 0.3
        ,"A": 4.0
        ,"A-": 4.0 - 0.3
        ,"B+": 3.0 + 0.3
        ,"B": 3.0
        ,"B-": 3.0 - 0.3
        ,"C+": 2.0 + 0.3
        ,"C": 2.0
        ,"C-": 2.0 - 0.3
        ,"D+": 1.0 + 0.3
        ,"D": 1.0
        ,"D-": 1.0 - 0.3
    }

    return gradhash[s]

print(gp('A-'))
lit
  • 14,456
  • 10
  • 65
  • 119