I am a beginner in python. I am making a Toss Simulator. This is my code:
import random
class TossSimulator():
heads = 0
tails = 0
def doFlip(self):
x = random.randint(0,1)
if(x == 0):
return True
else:
return False
def getScore(self, flip_function):
if flip_function is True:
self.heads+=1
else:
self.tails+=1
obj = TossSimulator()
obj.getScore(doFlip())
The error I am recieving is :
NameError : name 'doFlip' is not defined at line 24
1 Answer 1
You really do not need a class for this, but if you just want to practice, then practice well! The problem is, as stated in the comments, that doFlip does not exist in the scope in which you are trying to call it. Wrapping some of the comments up into a solution that illustrates some nice features:
import random
class TossSimulator():
def __init__(self, flip_function):
"""
Args:
flip_function: function that returns True (heads) or False (tails)
"""
self.heads = 0
self.tails = 0
self.flip = flip_function
def get_score(self):
if self.flip(): # call stored flip function
self.heads += 1
else:
self.tails += 1
print('Heads: {}\tTails: {}'.format(self.heads, self.tails))
def do_flip():
return random.randint(0, 1) == 0 # skip the middle man
obj = TossSimulator(do_flip)
obj.get_score() # prints the running total heads and tails
# Heads: 0 Tails: 1
A couple of important changes were made. First, I added the __init__ function, which is the constructor for Python objects. This is where you want to define any of your member variables, initialize things, etc. With the class defined this way, you can make multiple instances of your TossSimulator and they will each keep a record of their own scores:
obj1 = TossSimulator(do_flip)
obj2 = TossSimulator(do_flip)
obj1.getScore() # Heads: 1 Tails: 0
obj1.getScore() # Heads: 1 Tails: 1
obj2.getScore() # Heads: 0 Tails: 1 (scored separately)
obj2.getScore() # Heads: 0 Tails: 2
Second, I made flip_function a parameter that is passed to your constructor. Now you can define a special flip function for each instance of your TossSimulator when you create it, and then get_score will use the flip function defined for that instance every time you call it:
def always_heads():
return True
obj1 = TossSimulator(do_flip)
obj2 = TossSimulator(always_heads)
obj1.getScore() # Heads: 0 Tails: 1
obj1.getScore() # Heads: 1 Tails: 1 (random flips)
obj2.getScore() # Heads: 1 Tails: 0
obj2.getScore() # Heads: 2 Tails: 0 (always will be heads)
Third, I cleaned a couple of things up. You can, for instance, replace something like this:
if x == y:
return True
else:
return False
with return x == y. They're exactly the same, but one is much more concise (and possibly very slightly more efficient?). You can also directly check the "truthiness" of a function's return, so you do not need to use if self.flip() == True:; you can just use if self.flip():.
You can take that last point a step further and directly check the "truthiness" of a numeric value. In Python, zero is False and all other integers are True. A summary of what values are true and what values are false can be found here.
doFlipisn't defined at the scope where you called it; it's a method of theTossSimulatorclass.obj.getScore(obj.doFlip())doFlipdoesn't use an instance ofTossSimulator, so it should be defined as a regular function outside the class.getScoreis misleading; you aren't passing a function as an argument, but a Boolean value.__init__method and not rely on class variables.