Reputation: 1237
I'm trying to make a piece of code that will count up votes for three different candidates, and I'm using a function that uses the variable name (either A, B or C) as a parameter.
I'm trying to have it so that whenever a vote is counted for that candidate, it will call the function to increase the variable for that candidate by 1. However, with every way I've tried all 3 candidates will always have 0 votes counted, unless I completely remove the function.
I've tried several different ways of making the variables global variables but they all gave the same results.
A = 0
B = 0
C = 0
def after_vote(letter):
letter = letter + 1
print("Thank you for your vote.")
def winner(winner_letter, winner_votes):
print("The winner was", winner_letter, "with", str(winner_votes), "votes.")
while True:
vote = input("Please vote for either Candidate A, B or C. ").upper()
if vote == "A":
after_vote(A)
elif vote == "B":
after_vote(B)
elif vote == "C":
after_vote(C)
elif vote == "END":
print("Cadidate A got", str(A), "votes, Candidate B got", str(B), "votes, and Candidate C got", str(C), "votes.")
if A > B and A > C:
winner("A", A)
break
elif B > A and B > C:
winner("B", B)
break
elif C > A and C > B:
winner("C", C)
break
else:
print("There was no clear winner.")
break
else:
print("Please input a valid option.")
Upvotes: 4
Views: 4365
Reputation: 19372
First of all, the idea is wrong. You don't want to handle global variables and pass names around. It could be done, but it is a bad idea.
A better option is to pass the variable to be modified to the function. However, the trick with integers is that they are immutable, so you cannot pass an integer to be modified by the function, as you would in C for instance.
What is left is either:
That was the theory, here is how to do it...
def after_vote(value):
print("Thank you for your vote.")
# Instead of modifying value (impossible), return a different value
return value + 1
A = after_vote(A)
class MutableInteger:
def __init__(value):
self.value = value
A = MutableInteger(0)
def after_vote(count):
# Integers cant be modified, but a _different_ integer can be put
# into the "value" attribute of the mutable count object
count.value += 1
print("Thank you for your vote.")
after_vote(A)
votes = {'A': 0, 'B': 0, 'C': 0}
def after_vote(votes, choice):
# Dictionaries are mutable, so you can update their values
votes[choice] += 1
print("Thank you for your vote.")
after_vote(votes, "A")
def after_vote(letter):
# Global variables are kept in a dictionary. globals() returns that dict
# WARNING: I've never seen code which does this for a *good* reason
globals()[letter] += 1
print("Thank you for your vote.")
Upvotes: 6
Reputation: 2299
The easiest way to do this would be to use a dict, if no two candidates will share the same name.
candidates = {"A":0, "B":0, "C":0}
From there, you could set up a function to look up a value in the dictionary and increment it:
def update_vote(candidate):
candidates[candidate] += 1
Or heck, you could just update the votes in-place rather than calling a function with:
candidates[candidate] += 1
A much more pythonic way of doing this would be to make each candidate an object that can update its own vote count.
class Candidate(object):
def __init__(self):
# This is the "constructor" for the object.
# It is run whenever an instance of this object is created.
# We want it to "spawn in" with zero votes.
self.vote_count = 0
def update_vote(self):
self.vote_count += 1
This seems to be closer to what you were getting at in your initial post. You would create an object as follows:
A = Candidate()
B = Candidate()
C = Candidate()
And then, in your main loop, you would just tell each object to update itself:
if vote == "A":
A.update_vote()
Finally, when you're tallying up the votes, you would just ask each object to give you their "vote" count:
if A.vote_count > B.vote_count and A.vote_count > C.vote_count
Upvotes: 2
Reputation: 22992
In your situation, it is better to define 3 function, one for each candidate:
A = 0
B = 0
C = 0
def after_vote_A():
global A
A += 1
print("Thank you for your vote.")
def after_vote_B():
global B
B += 1
print("Thank you for your vote.")
def after_vote_C():
global C
C += 1
print("Thank you for your vote.")
Don’t forget to use the keyword global
or else you define a local variable.
An alternative is to store votes in a dict
:
votes = {'A': 0, 'B': 0, 'C': 0}
def after_vote(letter):
votes[letter] += 1
print("Thank you for your vote.")
Démonstration:
after_vote('A')
after_vote('B')
after_vote('A')
after_vote('A')
print(votes)
You get:
Thank you for your vote.
Thank you for your vote.
Thank you for your vote.
Thank you for your vote.
{'A': 3, 'B': 1, 'C': 0}
Upvotes: 2
Reputation: 1695
You need to pass a mutable data type into function, so that you can modify it. Try wrapping your candidates into a list or dictionary.
candidates = {'A':0, 'B':0, 'C':0}
def after_vote(letter):
global candidates
if letter in candidates:
candidates[letter] += 1
print("Thank you for your vote.")
else:
print("No such candidate: Your vote is invalid.")
Upvotes: 1