2

I want to write a function to compare two values, val1 and val2, and if val1 is larger than val2, add 1 point to a_points (Think of it like Team A) and vice versa (add one point to b_points if val2 is larger.) If the two values are even I won't add any points to a_points or b_points.

My problem is test_val will not return the values of a_points or b_points.

a_points=0
b_points=0

def test_val(a_points,b_points,val1,val2):
    if val1 > val2:
        a_points+=1
        return a_points
    elif val2 > val1:
        b_points+=1
        return b_points
    elif val1==val2:
         pass

Here's a link to a visualization showing the problem.

Kristen Huber
  • 31
  • 1
  • 1
  • 4
  • As shown in your visualization, `a_points` and `b_points` inside the function aren't the same as the global variables. So modifying them inside the function won't modify the global ones. You might be interested in the `global` keyword (aka add `global a_points, b_points`) or in the `return` keyword. – xZise Nov 23 '16 at 10:52

7 Answers7

3

Consider this:

a0=5
a1=6
a2=7
b0=3
b1=6
b2=10
a_points=0
b_points=0

def test_val(a_points, b_points, val1, val2):
    if val1 > val2:
        a_points += 1
        return (a_points, b_points)
    elif val2 > val1:
        b_points += 1
        return (a_points, b_points)
    elif val1==val2:
        return (a_points, b_points)

a_points, b_points = test_val(a_points,b_points, a0, b0)
a_points, b_points = test_val(a_points,b_points, a1, b1)
a_points, b_points = test_val(a_points,b_points, a2, b2)

print(a_points, b_points)

Good luck!

opalczynski
  • 1,599
  • 12
  • 14
  • 1
    I think returning both values as Sebastian suggests is the best solution. This way the function has always the same output. I would put only one `return (a_points, b_points)` at the end of the function and remove the `elif` statement, but these are just minor enhancements (as Gormador posted just now) – Leonardo Giordani Nov 23 '16 at 11:06
  • Very easy to understand. Thank you! – Kristen Huber Nov 25 '16 at 09:23
2

Global variables are generally a bad idea. Don't use them unless you really have to.

The proper way to implement such counter is to use a class.

class MyCounter(object):

    def __init__(self):
        self.a_points = 0
        self.b_points = 0

    def test_val(self, val1, val2):
        if val1 > val2:
            self.a_points += 1
        elif val2 > val1:
            self.b_points += 1
        else:
            pass

counter = MyCounter()
counter.test_val(1, 2)
counter.test_val(1, 3)
counter.test_val(5, 3)
print(counter.a_points, counter.b_points)

Output:

(1, 2)

Note that returning a value from test_val doesn't make sense, because caller has no way to know if she gets a_points or b_points, so she can't use return value in any meaningful way.

alexanderlukanin13
  • 4,577
  • 26
  • 29
  • This is EXACTLY what I wanted to do! I **tried** to make it into a class before but I failed and then the above-mentioned problem happened and I felt it was best to keep it simple. Thank you so much! – Kristen Huber Nov 25 '16 at 09:21
  • @KristenHuber You can upvote my answer if you find it helpful. – alexanderlukanin13 Nov 26 '16 at 15:21
0
a_points=0
b_points=0

def test_val(a_points,b_points,val1,val2):
    global a_points
    global b_points

    if val1 > val2:
        a_points+=1
        return a_points
    elif val2 > val1:
        b_points+=1
        return b_points

    elif val1==val2:
         # If you pass, it won't return a_points nor b_points
         return a_points # or b_points
Carles Mitjans
  • 4,786
  • 3
  • 19
  • 38
0
print (test_val(a_points,b_points,1,2))
print (test_val(a_points,b_points,2,1))
print (test_val(a_points,b_points,2,2))

This will give you a result:

1
1
None

Hence you should not look at the function to return values, rather it updates the values of variables a_points and b_points. That is why in the link that you shared the code includes a print(a_points,b_points) statement at the end

Gaurav Dhama
  • 1,346
  • 8
  • 19
0

This will simplify your code and logic. And make it work ;-)

a0=5
a1=6
a2=7
b0=3
b1=6
b2=10
a_points=0
b_points=0

def test_val(a_points,b_points,val1,val2):
    if val1 > val2:
        a_points+=1

    elif val2 > val1:
        b_points+=1

    return a_points, b_points



a_points, b_points = test_val(a_points,b_points,a0,b0)
a_points, b_points = test_val(a_points,b_points,a1,b1)
a_points, b_points = test_val(a_points,b_points,a2,b2)

print(a_points,b_points)
Gormador
  • 380
  • 2
  • 15
0

Your problem is the that Python integers are immutable which in general is good to read about. A few more details can be found here.

Now, regarding solutions:

  1. As suggested, you can use global variables. Keep in mind this is usually considered bad practice cause it leads to messy code... but globals have their place in programming.

  2. Also suggested, you can always return both a_points and b_points

  3. Use lists to keep score:

    • The test_val will return either 0, 1 or 2 where 0 means equal, 1 means the first argument is larger and 2 means the second argument is larger.
    • Your main script will have a list with the above indexes where it will "keep score"

The code:

a0=5
a1=6
a2=7
b0=3
b1=6
b2=10
points=[0, 0, 0]


def test_val(val1,val2):
    if val1 > val2:
        return 1
    elif val2 > val1:
        return 2
    elif val1==val2:
        return 0

points[test_val(a0,b0)] += 1
points[test_val(a1,b1)] += 1
points[test_val(a2,b2)] += 1

print("eq=%d, A=%d, B=%d" % (points[0], points[1], points[2]))

Output (visualize)

eq=1, A=1, B=1

Hope it helps

Community
  • 1
  • 1
urban
  • 5,392
  • 3
  • 19
  • 45
-2

Note that a_points and b_points shadow your global variables, since they are also passed as parameters.

Any way, you are not returning value in case of equality, instead of pass, return a value

def test_val(a_points,b_points,val1,val2):
    if val1 > val2:
        a_points+=1
        return a_points
    elif val2 > val1:
        b_points+=1
        return b_points
    elif val1==val2:
         return a_points
Blair d
  • 78
  • 5