# Hello World! program.
def main():
#get the user's name
= input('What is your name? ')
name print('Hello World! I am', name)
# Call the main function
main()
This was quite a journey for me. I started the same way everyone else has; with my very first “Hello World” program written in Python 3:
This was the first assignment for my Programming in Python course. I was not content to have it only print “Hello World”—no, I need to personalize it in some small way. The following was really interface (if I’m speaking pythonically); to a wider interest in programming qua programming:
= input('What is your name? ') name
Nevertheless, I was not content with this. I allowed myself to be sucked into a forceful vortex that had me thinking I’d be using Jupytr notebooks, matplotlib, etc., to show off how much I know about Python from Twitter. Notwithstanding, the above is what was submitted because I didn’t know how to do any of the fancy stuff I read about. I didn’t know how to use Pandas. I didn’t know how to use Blaze. I didn’t even know how to use ‘conda update conda’ in my terminal (oh; it’s a package manager—not just an easy way to install Python 3.4 on my computer at work without Admin privlages!).
The reality is that I still have a lot to learn—I’m still in the shallow end. Nothing prepared me for the absolute angst associated with trying to implement a (beginner’s attempt at) the Object Oriented Programming (OOP) paradigm as a final extra-credit assignment! I didn’t even know I had been writing, although very functional; or, very function reliant, procedural code. Somewhere between nesting lists inside of dictionaries, iterating over them, and implementing ‘try, except’ statements, I thought I was really going places with my code. OOP razed that sandcastle quite briskly. Like a kind of soverign and violent natural phenomena.
From my first program to my 10th program, this is how far I have come. This is my attempt at OOP, classes, ‘init’ methods, inheritance composition, and more. It’s likely pretty flawed and could be made less redundant, but I didn’t copy StackOverflow and tried to figure it out on my own; so, I’m damn proud of it! There were some programs specs that I needed to show an understanding of; quickly, the program specs:
- Each question will have four possible answers
- Each player will take turns with the questions
- There will be a total of 10 questions, each player getting a chance to answer five of them. If the player selects the correct answer, they earn a point. Tell the player whether they got it right or wrong.
- Must create a ‘Question’ class to hold data with the following attributes:
- A trivia question
- Possible answer 1
- Possible answer 2
- Possible answer 3
- Possible answer 4
- The number of the correct answer, e.g., 1, 2, 3, or 4
- Question class must have an ‘init’ method, accessors, mutators, and a ‘str’ method.
- Use value-returning functions; one named createQuestionsAnswers() that creates the list to display questions and keeps tracks of user input to let players know if they won, lost, or tied.
Here are my solutions:
# -*- coding: utf-8 -*-
""" A10--Trivia Game!
--> two player trivia game
--> OOP approach to building the game with classes and objects
"""
import csv
import random
# the Question class acts as a placeholder for the parts of the question
# needed to construct questions and check answers
class Question:
# __init__ uses the Data class method getData through composition
def __init__(self, question, a1, a2, a3, a4, answer, ansNum):
self.getData = Data('csv')
self.question = question
self.a1 = a1
self.a2 = a2
self.a3 = a3
self.a4 = a4
self.answer = answer
self.ansNum = ansNum
# the method performs better as a class method since it instantiates the
# Question class with sample questions for the game
@classmethod
def getQuestion(cls, triviaDict):
# using random to get 10 random numbers between a specific range for
# trivia questions
= random.sample(range(1, 817), 1)
randomGenerator
# for an individual random number in the sample range
# --> iterate and use number as index for the trivia questions
for i in randomGenerator:
= triviaDict[i][0]
question = triviaDict[i][1]
a1 = triviaDict[i][2]
a2= triviaDict[i][3]
a3 = triviaDict[i][4]
a4 = triviaDict[i][5]
answer = triviaDict[i][6]
ansNum
# this creates an instance to return (from question class)
= Question(question, a1, a2, a3, a4, answer, ansNum)
aQuestion return aQuestion
# this is a part of using composition rather than inheritance to get the
# attributes from the getData method
def __getattr__(self, attr):
return getattr(self.getData, attr)
# this method sets up the question (also checks answer)
@classmethod
def setupAsk(cls, q):
print('\n', q.question, '\n\t1: ', q.a1, ' \
\n\t2: ', q.a2, '\n\t3: ', q.a3, ' \
\n\t4: ', q.a4, '\n')
# make sure the user's input works
while True:
try:
= int(input("\nWhat's your answer? \n--> "))
choice except ValueError:
print('\nSorry, the answer only accepts numbers; please \
enter a number 1-4')
= int(input("\nWhat's your answer? \n--> "))
choice finally:
if choice in range(1, 5):
break
# if the question is correct, return true; if not, return false
if choice == q.ansNum:
print('\nCorrect! \n', q.answer)
return True
elif choice != q.ansNum:
print('\nIncorrect! \n', q.answer)
return False
# the Data class handles openning the file and preparing it to be used by
# the Question and Game class
class Data:
def __init__(self, filetype):
self.filetype = filetype
# opens the CSV to read and prepare it to be used in computaiton later
@classmethod
def getData(cls):
# make sure there isn't an IO error
try:
# open the csv file + use an index accumulator for dictionary
with open('trivia.csv') as csvFile:
= csv.reader(csvFile, delimiter=',')
readCSV = 0
index
# questions, answer choices, and answers dictionary
= {}
rowDict = {}
questionData # reading the trivia questions
for row in readCSV:
= row
rowDict[index] = rowDict[index][0]
question = rowDict[index][1]
a1 = rowDict[index][2]
a2 = rowDict[index][3]
a3 = rowDict[index][4]
a4 = rowDict[index][5]
answer
# figure out which answer is correct and assign a variable
if answer == a1:
= 1
ansNum elif answer == a2:
= 2
ansNum elif answer == a3:
= 3
ansNum elif answer == a4:
= 4
ansNum else:
print("Error! No correct answer")
# place questions into new dictionary in the right order
= [question, a1, a2, a3, a4, \
questionData[index]
answer, ansNum]+= 1
index
return questionData
except IOError:
print("The file could not be found.")
# the Game class is where the bulk of the game's structure is found
class Game:
def __init__(self, playerID, gamePoints):
self.playerID = playerID
self.gamePoints = gamePoints
# method to create instances for questions and find out if a quesiton
# was answered correctly or not
def round(self, qClass, data):
= 0 # reset to 0 for new round
gamePoints
# instances
= qClass.getQuestion(data)
q1 = qClass.getQuestion(data)
q2 = qClass.getQuestion(data)
q3 = qClass.getQuestion(data)
q4 = qClass.getQuestion(data)
q5
# return value is true or false; this computes points
if qClass.setupAsk(q1) == True:
+= 1
gamePoints if qClass.setupAsk(q2) == True:
+= 1
gamePoints if qClass.setupAsk(q3) == True:
+= 1
gamePoints if qClass.setupAsk(q4) == True:
+= 1
gamePoints if qClass.setupAsk(q5) == True:
+= 1
gamePoints
# let the user know what happenned this round
print('you won {} points this game!'.format(gamePoints))
return gamePoints
def main():
# local variables
= False
flag = 1
gameNum
# instance of Data class
= Data('csv')
data = data.getData()
questionsData
# instance of Question class with filler data
= Question('question', 'a1', 'a2', 'a3', 'a4', \
questions 'answer', 'ansNum')
# create both players
= Game(str(input('PLAYER ONE//\nEnter your name: ')), 0,)
playerOne = Game(str(input('PLAYER TWO//\nEnter your name: ')), 0,)
playerTwo
# while loop to keep the game going if the user chooses
while flag != True:
# let the user know which round they're playing
print('\nROUND ', gameNum, '//\nPlayer One')
# first player instance; asks five questions
= playerOne.round(questions, questionsData)
p1round
print("""
+++++++++++++++++++++++++++++++++++++++++++++++++
+ SWITCH PLAYERS! +
+++++++++++++++++++++++++++++++++++++++++++++++++
""")
# let the user know to switch players
print('\nROUND ', gameNum, '//\nPlayer Two')
# second player instance; asks the five quesitons
= playerTwo.round(questions, questionsData)
p2round
# let the user know which round they are on with accumulator
+= 1
gameNum
# figure out who won and use user's inputed name and their points
# in print statement
if p1round < p2round:
print('Thank you for playing! {} is the winner with {} total \
game points!'.format(playerTwo.playerID, p2round))
elif p2round < p1round:
print('Thank you for playing! {} is the winner with {} total \
game points!'.format(playerOne.playerID, p1round))
elif p2round == p1round:
print('There was a tie! Both {} and {} both earned {} total \
game points; but you are both still \
winners!'.format(playerOne.playerID, playerTwo.playerID, \
p1round))
# find out if user wants to continue + validate user response
while True:
try:
= str(input("\nKeep playing? \n--> ")).upper()
choice except ValueError:
print("Sorry, enter either a 'Y' for 'Yes', or 'N' for 'No'.")
finally:
if choice == 'N':
= True
flag break
if choice == 'Y':
break
else:
print("please enter either a 'Y' for 'Yes', or 'N' \
for 'No'.")
# say bye to players and quit the program
print('\nThank you for playing! See you next time!\n')
main()
I couldn’t help but think about Plato when I was trying to understand how Objects work in Python. There’s something really similar about how a ‘class’ has a kind of ontos—that it isn’t just a blueprint—it exists, and it did exist before the ‘init’ method gave it attributes; that prescriptive human speculation we come up with when describing the form of something abstract like ‘the Beautiful’ (although it’s been a while since my Phil 100A course at UCLA—I hope I’m not misrepresenting the Phaedo).
The course is over but I have a few titles I purchased from Packt to dig a little deeper. Suggestions are always welcome; the journey’s telos is to learn; and learn I intend to do!