How to run one function and then another function within the main() - python

So I am just learning Python and am working on an online exercises to get use to the language and software itself. Right now I am working on making one function (getData()) run and then the results from that function to run into another function (getStats()) that is all with a main(). Each one works individually but I am having a problem with the main(). I can get my first getData() to run and make my list but I can't get that list to run directly into getStats(). It actually runs the getData() again and then comes back with an error message when I put in an input . Does anyone have any suggestions for me to not get that error message and then to actually run my getStats()?
def getData():
import math
pop = []
while True:
user = raw_input("Please enter a population number (-1 to quit): ")
pop.append(user)
if user == '-1':
break
if user <= '0':
print "Population not valid, please input a value higher then 0"
new_pop = map(int, pop)
pop2 = filter(lambda x:x >=1, new_pop)
print "Your population list is: ", pop2
return
def getStats():
i = ""
asc = sorted(i)
print "The collected data in the asecending order", asc
dec = sorted(i, reverse = True)
print "The collected data in the descending order", dec
maxi = max(i)
print "The maximum of the collected data is", maxi
mini = min(i)
print "The minimum of the collected data is",mini
def getMean(i):
aver = round(sum(i), 2)/round(len(i), 2)
print "The average of the collected data is %.2f" % aver
getMean(i)
def getStdev(i):
aver = sum(i)/len(i)
var = sum(pow(user-aver,2) for user in i)/len(i)
stdev = math.sqrt(var)
print "The standard deviation of the collected data is %.2f" % stdev
return
def main():
getData()
getStats(getData())
main()

The variables inside each function cannot be accessed by other functions variable/function scope.
One way to use them is to have the function return those values. Here is a simplified example:
def get_data():
data = raw_input('Ask for data')
return data
def get_stats(data):
sorted_data = sorted(data)
print 'Sorted:', sorted_data
data = get_data() # get_data will point 'data' to the value returned
get_stats(data) # call get_stats, and pass 'data' as an argument
Some other thoughts:
You don't really need the main() function. It's not doing anything.
What is more common, is adding a conditional statement to only run this if you are running the file itself, but not when it's imported as a module:
if __name__ == '__main__':
data = get_data()
get_stats(data)
Check out PEP 008
Usually your imports should be at the beginning of the file (Imports)
Function names are camel_case

Related

How write User Input Data to External Text File?

I would like to be able to take the test scores the user inputs and write to an external text file. Then have the application read off the values from the and calculate the average. However, I am unsure as to how to implement the python syntax within the loop and the functions. I've attempted to utilize my resources to get a better idea of how to do this, but I've been having some trouble understanding how python handles external files. In addition, would using append be better than write in this scenario?
Current Syntax:
def testAvgCalculation():
#Variables
total = 0
total_quiz = 0
while True:
#User Input and Variable to stop loop
inpt = input("Enter score: ")
if inpt.lower()== 'stop':
break
#Data Validation
try:
if int(inpt) in range(1,101):
total += int(inpt)
total_quiz += 1
else:
print("Score too small or Big")
except ValueError:
print("Not a Number")
return total, total_quiz
def displayAverage(total, total_quiz):
average = total / total_quiz
print('The Average score is: ', format(average, '.2f'))
print('You have entered', total_quiz, 'scores')
#Main Function
def main():
total, total_quiz = testAvgCalculation()
displayAverage(total, total_quiz)
#Run Main Function
main()
This is hacky as heck, but I tried to work with what was already there. I split the data validation section of the original function off into a separate function. In main() it returns its value counter, which keeps track of how many values were entered, to calculate_average(), which then reads the file line by line until counter becomes 0, which means it's about to read the word "stop" (which allows EOF recognition via the 'and' in the if statement), performs the calculation and returns its values.
def write_file():
#Variables
counter = 0
file = open("Scores.txt", "w")
while True:
#User Input and Variable to stop loop
inpt = input("Enter score: ")
file.write(inpt + "\n")
if inpt.lower()== 'stop':
file.close()
break
counter += 1
return counter
def calculate_average(counter):
total = 0
total_quiz = counter
scores = open("Scores.txt", "r")
s = ""
try:
while counter > 0 and s != 'stop':
s = int(scores.readline())
if int(s) in range(1,101):
total += int(s)
counter -= 1
else:
print("Invalid data in file.")
except ValueError:
print("Invalid data found")
return total, total_quiz
def displayAverage(total, total_quiz):
average = total / total_quiz
print('The Average score is: ', format(average, '.2f'))
print('You have entered', total_quiz, 'scores')
#Main Function
def main():
total, total_quiz = calculate_average(write_file())
displayAverage(total, total_quiz)
#Run Main Function
main()
NOTE: the file is created initially in write mode which overwrites the file each time so you never need a new one. if you want to keep a record you might like to change it to append, though you'll need to manage extracting the proper lines from among old input.
Not pretty at all, but should give you an idea of how to accomplish what you were going for.

How to prevent printing from previous function in current function?

I'm currently writing a test function for class to test provided cases on provided solution code. However I'm running into an issue where a print statement is executing when I don't want it to.
This is the provided solution that I'm testing:
def alphapinDecode(tone):
phone_num = ''
if checkTone(tone): #or checkTone2
while len(tone) > 0:
# retrieve the first tone
next_tone = tone[0:2]
tone = tone[2:]
# find its position
cons = next_tone[0]
vow = next_tone[1]
num1 = consonants.find(cons)
num2 = vowels.find(vow)
# reconstruct this part of the number -
# multiply (was divided) and add back
# the remainder from the encryption division.
phone = (num1 * 5) + num2
# recreate the number
# by treating it as a string
phone = str(phone)
# if single digit, not leading digit, add 0
if len(phone) == 1 and phone_num != '':
phone = '0' + phone
phone_num = phone_num + phone
# but return in original format
phone_num = int(phone_num)
else:
print('Tone is not in correct format.')
phone_num = -1
return phone_num
Here's the (partially done) code for the test function I have written:
def test_decode(f):
testCases = (
('lo', 43),
('hi', 27),
('bomelela', 3464140),
('bomeluco', 3464408),
('', -1),
('abcd', -1),
('diju', 1234),
)
for i in range(len(testCases)):
if f(testCases[i][0]) == testCases[i][1] and testCases[i][1] == -1:
print('Checking '+ f.__name__ + '(' + testCases[i][0] + ')...Tone is not in correct format.')
print('Its value -1 is correct!')
return None
When executing test_decode(alphapinDecode), I get this:
Tone is not in correct format.
Checking alphapinDecode()...Tone is not in correct format.
Its value -1 is correct!
Tone is not in correct format.
Checking alphapinDecode(abcd)...Tone is not in correct format.
Its value -1 is correct!
As you can see, because of the print statement in alphapinDecode(I think), it is printing an extra "Tone is not in correct format." above the print statement I have written.
How would I prevent this print statement from executing, and why is it printing if the print statement I wrote in my test function doesn't ask for the result of alphapinDecode?
We are not allowed to alter the code of the given solution.
I'm fairly new to stackOverflow, so sorry for any formatting issues. Thank you!
Edit: Fixed the idents of the test_decode function
One easy solution would be to pass an extra parameter say, a boolean variable debug to the function. That would go something like this.
def func1(var1, debug):
if debug:
print("Printing from func1")
# Do additional stuff
Now when you call it. You now have the option of setting the debug variable.
func1("hello", debug=True) # will print the statement
func1("hello", debug=False) # will not print statement.
If you cannot modify the called function. Then you can follow this method. explained by #FakeRainBrigand here.
import sys, os
# Disable
def blockPrint():
sys.stdout = open(os.devnull, 'w')
# Restore
def enablePrint():
sys.stdout = sys.__stdout__
print 'This will print'
blockPrint()
print "This won't"
enablePrint()
print "This will too"

Difficulties with an unruly program

I have been working on this code for a couple of hours now, and I am rather unsure what the problem is.
import random#imports random
import os#Imports os
print("Welcome to the maths quiz") # Welcomes user to quiz
score = (0)
def details():
plr_name = input ("Please Input Name:") # Asks user for name
plr_class = input("Input class number: ") # Asks the user for class numer
return (plr_name, plr_class)
def Q():
while qno < 10: # loops while qno is under 10
ran_num1 = random.randint(1,99) # Generates the first random number
ran_num2 = random.randint(1,99) # Generates the second random number
ran_fun = random.choice("X-+") # Picks a random function
print(ran_num1,ran_fun,ran_num2,"=") # Prints the Sum for the user
if ran_fun == "X":
sum_ans = ran_num1 * ran_num2 # Does the sum if it is a multiplication
if ran_fun == "+":
sum_ans = ran_num1 + ran_num2 # Does the sum if it is a addition
if ran_fun == "-":
sum_ans = ran_num1 - ran_num2 # Does the sum if it is a subtraction
plr_ans = int(input()) # Gets the user's answer
if plr_ans == sum_ans:
print("Correct!") # Prints correct
score = score + 1 # Adds 1 to score
else:
print("Incorrect!")
qno = qno + 1 # Adds 1 to qno
def plr_list_make(lines, listoreder):
index = 0
plr_names =[]
plr_scores =[]
for line in lines:
if listorder == 1:
column =0
rev = False
else:
column = 1
rev = True
return sorted(zip(plr_names, plr_scores),key = lambda x:(x[column]),reverse = rev)
def fileUP(plr_name, score, line ):
found = False
index = 0
for line in lines:
if line.startswith(plr_name):
line = line.strip("\n") + ","+str(score+"\n")
lines[index] = line
found = True
index = index + 1
if not found:
lines.append(plr_name+"|" +str(score)+"\n")
return lines
def save (plr_name, plr_class, score):
filename = "QuizScore_"+plr_class+".txt"
try:
fileI = open(filename)
except IOError:
fileI = open(filename, "w+")
fileI = open(filename)
lines = fileI.readlines()
fileI.close
lines = FileUP(plr_name, score, lines)
fileO = open(filename, "w")
fileO.writelines(lines)
fileO.close
def disp_list(): ## intialise_list
student_list=[]
filename = "QuizScore_"+plr_class+".txt"
try:
## open file read into list "lines"
input_file = open(filename)
lines = input_file.readlines() ## read file into list "lines"
input_file.close
student_list = create_student_list(lines, listorder) ### update "lines" with student list as requested by user
## output sorted list
for counter in range(len(student_list)):
print ("Name and Score: ", student_list[counter][0], student_list[counter][1])
except IOError:
print ("no class file!!!")
def menu():
print ("1 Test")
print ("2 Alphabetical")
print ("3 Highscore")
print ("4 Avg Score")
def Run():
selection = 0
while selection != 5:
menu()
option = int(input("Please select option: "))
if option == 1:
name, plr_class = details()
save(name, plr_class, Q())
else:
plr_class = input("input class ")
disp_list(plr_class, option-1)
Run()
Errors:
Traceback (most recent call last):
File "C:\Users\user\Documents\CharlieStockham\cgsca\ca2.py", line 117, in
Run()
File "C:\Users\user\Documents\CharlieStockham\cgsca\ca2.py", line 113, in Run
save(name, plr_class, Q())
File "C:\Users\user\Documents\CharlieStockham\cgsca\ca2.py", line 74, in save
lines = FileUP(plr_name, score, lines)
NameError: global name 'FileUP' is not defined
Line 110:
name, plr_class = details()
But the details function does not return anything - so Python tries to assign the default return value None to the tuple name, plr_class. It can't do this, because None is not an iterable (you can't assign two things to it). To fix it, add the following line to your details function:
return (plr_name, plr_class)
(I haven't tested this.)
I like your game but it's buggy as a mofo :P
score and qno aren't properly defined. Define them in the functions that need them, define them globally or pass them to the relevant functions as arguments.
details() doesn't return anything but you still attempt to use its output to define two other variables. Add return (plr_name, plr_class) to details()
Every time you cast user input to int without checking its value, your program will crash if an int can't be cast. This applies here:
option = int(input("Please select option: "))
here
plr_ans = int(input())#Gets the user's answer
and elsewhere.
Since your program is input-heavy you could make a a function to which you pass the expected datatype and an optional string to display to the user. This way you wouldn't have to write try/except 10 times and your program wouldn't crash on unexpected input.
In def fileUP(plr_name, score, line ): you have for line in lines: but lines isn't defined. Thus, the save() function that calls FileUP() also fails. Also, FileUP and fileUP are not the same thing. You call the function with a capital "f" but the defintion of the function calls it fileUP with a lower case "f".
While we're at it, the file handling in def save (plr_name, plr_class, score):looks weird. The standard way of opening files for simple reading and writing in Python is via with open().
disp_list() should take one or two arguments but it doesn't at the moment so this error is raised:
TypeError: disp_list() takes 0 positional arguments but 2 were given
These 2 positional arguments were given here:
disp_list(plr_class, option-1)

python input check function not being called properly

I'm working on a very simple temperature converter in Python (just for practice), and am struggling with some of the UX components. I'd like to have checks in place to continue prompting for variable input when invalid entries are made. My full code is below:
o_temp = ''
def temp_input(o_temp):
o_temp = raw_input('Enter a temperature (round to nearest integer): ')
return o_temp
def temp_input_check(o_temp):
o_temp = list(o_temp)
for i in o_temp:
if i not in '1234567890':
print 'Invalid entry. Please enter only the numerical temperature measurement in integer format.'
temp_input(o_temp)
else:
break
def converter(o_temp):
unit = raw_input('Convert to (F)ahrenheit or (C)elsius? ')
unit = unit.upper()
if unit == 'F' or unit == 'f':
n_temp = (9.0/5.0) * int(o_temp) + 32
print '%d C = %d F' % (o_temp, n_temp)
quit()
elif unit == 'C' or unit == 'c':
n_temp = (5.0/9.0) * (int(o_temp) - 32)
print '%d F = %d C' % (o_temp, n_temp)
quit()
else: #check for valid entry
print 'Invalid entry. Please enter F for Fahrenheit or C for Celsius'
unit_input()
def temp_converter():
#title, call sub-functions
print ''
print 'Temperature Converter'
print ''
temp_input(o_temp)
temp_input_check(o_temp)
converter(o_temp)
temp_converter()
However, when I enter an invalid entry (say, a letter or a combination of letters and numbers) into the o_temp prompt, the code does not seem to recognize that this is invalid and continues with the unit prompt. Am I not correctly returning the variable? What's the issue here? I tried removing the initial o_temp declaration but then I got "NameError: global name 'o_temp' is not defined"
EDIT
I came up with this solution, any further suggestions to refine the code at all?
def converter():
print 'Temperature Converter'
while 1:
temp = raw_input('Starting temperature? ')
try:
temp = float(temp)
except ValueError:
print 'Invalid entry. Please enter only the numerical temperature measurement.'
else:
break
while 1:
unit = raw_input('Convert to Fahrenheit or Celsius? ')
if unit.upper().startswith('F') == True:
print "%f C = %f F" % (temp, temp*9./5+32)
return False
elif unit.upper().startswith('C') == True:
print "%f F = %f C" % (temp, (temp-32)*5./9)
return False
else:
print 'Invalid entry. Please enter F for Fahrenheit or C for Celsius'
converter()
You define some functions, then call temp_coverter(). This function calls temp_input(otemp), sending it an empty string for no reason that I can see, other than the possibility that you're unaware that you can define a function with no parameters. This function then returns a value, which you don't save.
After that, temp_input_check(otemp) is called, which attempts to validate the same empty string. This function's returned value isn't saved, which isn't a big loss, because None isn't a particularly useful value to save.
Then converter(otemp) sends the same old empty string to the actual converter. Mayhem results.
I recommend spending some quality time with the tutorial.
When you're done, the code should look more like this:
def converter():
print 'Temperature Converter'
unit = raw_input('Convert to Fahrenheit or Celsius? ')
while 1:
temp = raw_input('Starting temperature? ')
try:
temp = float(temp)
except ValueError:
print 'Not a valid temperature.'
else:
break
if unit.lower().startswith('f'):
print "%f C = %f F" % (temp, temp*9./5+32)
else:
print "%f F = %f C" % (temp, (temp-32)*5./9)
converter()
Your for loop isn't implemented correctly.
def temp_input_check(o_temp):
o_temp = list(o_temp)
for i in o_temp:
if i not in '1234567890':
print 'Invalid entry. Please enter only the numerical temperature measurement in integer format.'
temp_input(o_temp)
else:
break
You check every character for an invalid entry. If you typed in multiple invalid characters, it'll keep hitting the trigger after you have already determined that the string is invalid!
Also, if your first character is valid, you're telling it to break from the for loop (in your code 1fdsdfdsf would be a valid temperature, because it would skip every character after hitting that else statement and breakout from the loop).
Also, your temp_input doesn't need to accept an argument in the function (you're just gonna return the user's input). You actually want to assign it after you call the function instead of having it as an argument
Also, you're calling temp_input again to get the user input, but not capturing that anywhere with a return - so it's ultimately not doing anything. You should have your function return a True or False, and then catch that on the outside of the checker if you want to have the user try and enter a better temperature:
def temp_input_check(o_temp):
o_temp = list(o_temp)
for i in o_temp:
if i not in '1234567890':
print 'Invalid entry. Please enter only the numerical temperature measurement in integer format.'
return False
else:
pass # nothing is wrong with this character, keep checking
return True # if we hit this line, there were no problem characters
Then, when you call the stuff:
while(1):
o_temp = temp_input()
if temp_input_check(o_temp):
break # this means our o_temp is allllright.
# otherwise, go back to the start of the loop and ask for another temp
converter(o_temp)
because you mentioned 'o_temp' as the function parameter in the end but mentioned it as a empty string at Start. Don't give same names for global & function variables (just to avoid confusion). the function took the o_temp you mentioned above as parameter and neglects the one inside them.
Also the raw_input won't consider the input as string. Try input instead to avoid the sensibility of not using str to correct the loop.
This will do:
def converter():
o_temp = float(raw_input('Enter a temperature (round to nearest integer): '))
for i in str(o_temp):
if i not in ['1','2','3','4','5','6','7','8','9','0','.']:
print 'Invalid entry. Please enter only the numerical temperature measurement in integer format.'
unit = raw_input('Convert to (F)ahrenheit or (C)elsius? ')
if unit in ['f','F']:
n_temp = (9.0/5.0) * float(o_temp) + 32
print '%f C = %f F' % (o_temp, n_temp)
elif unit in ['c','C']:
n_temp = (5.0/9.0) * (float(o_temp) - 32)
print '%f F = %f C' % (o_temp, n_temp)
else: #check for valid entry
print 'Invalid entry. Please enter F for Fahrenheit or C for Celsius'
unit_input()
def temp_converter():
#title, call sub-functions
print ''
print 'Temperature Converter'
print ''
converter()
print temp_converter()

Problems transferring information from one part of a function to another

While working on my program I have run into a problem where the information stored in Menu option 1 is not being transferred to Menu option 2. As you can see it is correctly stored when in menu one. When it returns to go to menu option 2 its like it never went to option 1.
update #1:
some suggestions I've had is to understand scope? from what I can tell the program is not passing the data along to its parent program even though I've typed out return in each of the definitions.
#Must be able to store at least 4 grades
#Each class can have up to 6 tests and 8 hw's
#Weighted 40%*testavg 40% hw average attendance is 20%
#User must be able to input a minimum grade warning
#after each test the your program must calculate the students average and issue warning if necessary
##Define the Modules##
import math
def menu (a): #2nd thing to happen
menuend = 'a'
while menuend not in 'e':
menuend = raw_input("Type anything other then 'e' to continue:\n")
print "What would you like to do ?"
menudo = 0
print "1 - Enter Courses\n2 - Select Course to Edit\n3 - Save File\n4 - Load File\n5 - Exit\n"
menudo = input("Enter Selection:")
if (menudo == 1):
menuchck = 0
menuchck = raw_input("\nYou have entered #1 (y/n)?:\n")
if menuchck in ["Yes","yes","y","Y"]:
x = m1()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 2):
menuchck1 = 0
menuchck1 = raw_input("\nYou have entered #2 (y/n)?:\n")
if menuchck1 in ["Yes","yes","y","Y"]:
x = m2()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 3):
print "Entered 3"
elif (menudo == 4):
print "Entered 4"
else:
print "Anything Else Entered"
def course(): #3rd thing to happen
b = {}
while True:
while True:
print "\n",name,", please enter your courses below ('e' to end):"
coursename = raw_input("Course Name:")
if (coursename == 'e'):
break
will = None
while will not in ('y','n'):
will = raw_input('Ok for this name : %s ? (y/n)' % coursename)
if will=='y':
b[coursename] = {}
print "\n",name,", current course load:\n",b
coursechck = None
while coursechck not in ('y','n'):
coursechck = raw_input("Are your courses correct (y/n)")
if coursechck =='y':
return b
else:
b = {}
print
##Menu Options##
def m1():
a = course()
return a
def m2():
print "Excellent",name,"lets see what courses your enrolled in\n"
print x
return x
###User Input Section###
name = raw_input("Enter Students Name:\n")
a = {}
menu(a)
raw_input("This is the end, my only friend the end")
In your if-elif blocks in the do==1 case, you write m1(), but for the last case, you write x=m1(). You should have the latter everywhere (by typing m1() you only run the function, but do not store the returned x anywhere).
By the way, you can avoid this if-elif confusion using if chck in ["Yes","yes","Y","y"]:

Categories