First program:
import destinations
import currency
main_function = True
while (main_function):
def main():
# Determine length of stay
while True:
try:
length_of_stay = int(input("And how many days will you be staying in " + destination + "? "))
# Check for non-positive input
if (length_of_stay <= 0):
print("Please enter a positive number of days.")
continue
except ValueError:
print("The value you entered is invalid. Only numerical values are valid.")
else:
break
Second program:
def get_choice():
# Get destination choice
while True:
try:
choice = int(input("Where would you like to go? "))
if (choice < 1 or choice > 3):
print("Please select a choice between 1 and 3.")
continue
except ValueError:
print("The value you entered is invalid. Only numerical values are valid.")
else:
return choice
choice = get_choice()
def get_info(choice):
# Use numeric choice to look up destination info
# Rates are listed in euros per day
# Choice 1: Rome at €45/day
if (choice == 1):
return "Rome", 45
# Choice 2: Berlin at €18/day
elif (choice == 2):
return "Berlin", 18
# Choice 3: Vienna, €34/day
elif (choice == 3):
return "Vienna", 34
destination = get_info(choice)
Problem: First program runs with an error after input:
"NameError: name 'destination' is not defined"
Question: How is it that adding destination = get_info(choice) doesn't count as defining destination ?
What can I do to get the first program to agree with the input from the second program?
import destinations will run the module with that name, which should be on the PythonPath (otherwise it will raise an ImportError). So that's good. Once that file is run, all variables, functions, classes that were defined in it are accessible under the namespace destinations.
So in the file called destinations.py, if there is a variable called destination (which you made on the last line of file2), then you can access it as destinations.destination from within the first file (or any file that has the import statement import destinations).
You can read up on the different ways of importing items from different modules over at effbot. It will teach you that another attractive alternative for you would've been to write
from destinations import destination
and then your first file will work normally.
Note that the code you've copied here seems to have some indentation issues. Furthermore, you'll want to write (in the first file) destination[0] each time you need the word ("Rome", "Berlin", ..), because your function get_info from the 2nd file (destinations.py), returns a tuple (e.g. ("Rome", 45). You'll get a TypeError if you don't take that into account.
Related
Thanks firstly for bearing with me as a relative newcomer to the world of Python. I'm working on a simple set of code and have been racking my brain to understand where I am going wrong. I suspect it is a relatively simple thing to correct but all searches so far have been fruitless. If this has been covered before then please be gentle, I have looked for a couple of days!
I'm working on the following and after catching and correcting a number of issues I suspect that I'm on the last hurdle:-
def main():
our_list = []
ne = int(input('How many numbers do you wish to enter? '))
for i in range(0, (ne)): # set up loop to run user specified number of time
number=int(input('Choose a number:- '))
our_list.append(number) # append to our_list
print ('The list of numbers you have entered is ')
print (our_list)
main()
while True:
op = input ('For the mean type <1>, for the median type <2>, for the mode type <3>, to enter a new set of numbers type <4> or 5 to exit')
import statistics
if op == "1":
mn = statistics.mean(our_list)
print ("The mean of the values you have entered is:- ",mn)
if op == "2":
me = statistics.median(our_list)
print ("The median of the values you have entered is:- ",me)
if op == "3":
mo = statistics.mode(our_list)
print ("The mode of the values you have entered is:- ",mo)
if op == "5":
main()
else:
print("Goodbye")
break`
For some reason the appended (our_list) is not being recognised within the while true loop rendering the statistics calculation void. Any steer would be really appreciated as to where I am missing the obvious, thanks in advance.
Cheers
Bryan
I'm not sure exactly what you mean by "not being recognized", but our_list is a local variable inside main, so it can't be used anywhere but inside main.
So, if you try to use it elsewhere, you should get a NameError.
If your code actually has a global variable with the same name as the local variable that we aren't seeing here, things can be more confusing—you won't get a NameError, you'll get the value of the global variable, which isn't what you want.
The best solution here is to return the value from the function, and then have the caller use the returned value. For example:
def main():
our_list = []
ne = int(input('How many numbers do you wish to enter? '))
for i in range(0, (ne)): # set up loop to run user specified number of time
number=int(input('Choose a number:- '))
our_list.append(number) # append to our_list
print ('The list of numbers you have entered is ')
print (our_list)
return our_list
the_list = main()
while True:
op = input ('For the mean type <1>, for the median type <2>, for the mode type <3>, to enter a new set of numbers type <4> or 5 to exit')
import statistics
if op == "1":
mn = statistics.mean(the_list)
print ("The mean of the values you have entered is:- ",mn)
if op == "2":
me = statistics.median(the_list)
print ("The median of the values you have entered is:- ",me)
if op == "3":
mo = statistics.mode(the_list)
print ("The mode of the values you have entered is:- ",mo)
if op == "5":
the_list = main()
else:
print("Goodbye")
break
There are other options—you could pass in an empty list for main to fill, or use a global variable (or, better, a more restricted equivalent like an attribute on a class instance or a closure variable), or refactor your code so everyone who needs to access our_list is inside the same function… but I think this is the cleanest way to do what you're trying to do here.
By the way, this isn't quite the last hurdle—but you're very close:
After any mean, median, or mode, it's going to hit the "Goodbye" and exit instead of going back through the loop. Do you know about elif?
You mixed up '5' and '4' in the menu.
If the user enters 2 and 3 and asks for the mode, your code will dump a ValueError traceback to the screen; probably not what you want. Do you know try/except?
That's all I noticed, and they're all pretty simple things to add, so congrats in advance.
The issue is that our_list was defined in the main() function, and is not visible outside of the main() function scope.
Since you're doing everything in one chunk, you could remove line 1 and 6, taking the code from your main() function and putting it on the same indentation level as the code which follows.
This seems to be because you defined our_list within the main() function. You should probably define it as a global variable by creating it outside the main() function.
You could also put the while loop inside a function and pass in our_list as a parameter to the list.
How to open a file from the list of given files based on the user's input which is an integer
print("Enter 1.tp.txt\n2.c17testpat.pat\n3.c432testpat.pat\n4.c499testpat.pat\n5.c1335testpat.pat\n6.c6228testpat.pat")
user = input("Enter a number")
if user == 1:
filename = "tp.txt"
elif user == 2:
filename = "c17testpat.pat"
elif user == 3:
filename = "c432testpat"
elif user == 4:
filename = "c499testpat.pat"
elif user == 5:
filename = "c1355testpat.pat"
elif user == 6:
filename = "c6288testpat.pat"
fp = open(filename)
is there any other way to do it in python
this caused NameError: name 'filename' is not defined
You could store the file list as a Python list, like so:
files = ["filename_1", "filename_2", "filename_3"]
Then to print them, you would use a for loop:
for i, s in enumerate(files): # Use enumerate because we need to know which element it was
print(str(i + 1) + ": "+ s) # i + 1 because lists start from 0
To make sure your input is a number, use a while loop that exits only if the input is a valid number:
while True:
inp = input()
if inp.isdigit():
filename = files[int(inp) - 1] # - 1 because lists start from 0
break
else:
print("Enter a number")
You'll still need to make sure the number is not too big (or small, for that matter).
probably because you need to convert user to int first (might be a string as written). Also you should probably finish with a default case to throw an error if the user inputs a non sensical value...
As the question indicates a strong will to learn coding and already tried something, I offer a variant that works for python version 3 (in version 2 one would need raw_input instead of input and a future import to declare the print function):
#! /usr/bin/env python3
import sys
names_known = ( # Hints 1 and 2
None, "tp.txt", "c17testpat.pat", "c432test.pat",
"c499testpat.pat", "c1355testpat.pat", "c6288testpat.pat")
options_map = dict(zip(range(len(names_known)), names_known)) # 3
print("Enter:")
for choice, name in enumerate(names_known[1:], start=1): # 4
print('%d.%s' % (choice, name))
user_choice = input("Enter a number") # 5
try: # 6
entry_index = int(user_choice)
except:
sys.exit("No integer given!")
if not entry_index or entry_index not in options_map: # 7
sys.exit("No filename matching %d" % (entry_index,))
with open(options_map[entry_index]) as f: # 8
# do something with f
pass
Many things still can go wrong, and any error will need the user to restart (no while loops etc.), but some achievements
Have the names only stored once (here I picked a tuple)
Keep the 1 as first number in user interface (insert dummy at index 0)
Derive a dict from the tuple storing the names (dict offers fast lookup)
Build the user interface info from the name tuple (ignoring the dummy)
Separate input from validation
Check domain type first (integer). If fails exit early via sys.exit and give info
Check domain membership otherwise exit with info
open the resource filename targets in a context block so you do not forget to close when done with the processing
Not python but worth to know how to use it via bash.
A simple bash sample that list a folder content and let's user choose the file by the index.
# menu.sh
# usage: bash menu.sh FOLDER
select FILENAME in $1/*;
do
case $FILENAME in
"$QUIT")
echo "Exiting."
break
;;
*)
echo "You picked $FILENAME ($REPLY)"
chmod go-rwx "$FILENAME"
;;
esac
done
Credit http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_06.html
I have a piece of code (seen below) which enables me to be able to ask pupils a series of random questions and then save their name and scores to a file. I combined the name and score into a single variable called info, with the name coming first then the score. I now need to sort this information in order of score. Is there a way for me to make the score go in front of the name temporarily in the entire file so that I can use the sorted function to get it to go from lowest to highest?
Any help would be greatly appreciated!!! Thank you.
import random
import time
Name=input("What is your name?")
Class=input("Are you in Class A, B or C?")
print("Welcome" ,Name, "to the Maths Quiz!!")
time.sleep(3)
QuestionNumber=0
Operations=["+","-","x"]
answer=0
score=0
while QuestionNumber < 10:
Num1=random.randint(1,12)
Num2=random.randint(1,12)
QuestionNumber=QuestionNumber+1
operation = random.choice(Operations)
print("What is", Num1 ,operation, Num2)
guess=int(input("What is the answer to this question?"))
if operation =="+":
answer=Num1+Num2
elif operation =="-":
answer=Num1-Num2
elif operation =="x":
answer=Num1*Num2
if guess==answer:
score=score+1
print ("Correct")
else:
print("Incorrect")
print("Well done You got", score, "Out of 10!!")
score=str((score))
Info= (Name + (" ") + score)
if Class=="A":
ClassA=open("Class A Results.txt","a")
ClassA.write(Info)
ClassA.write(" \n")
ClassA.close()
elif Class=="B":
ClassB=open("Class B Results.txt","a")
ClassB.write(Info)
ClassB.write(" \n")
ClassB.close()
elif Class=="C":
ClassC=open("Class C Results.txt","a")
ClassC.write(" \n")
ClassC.write(Info)
ClassC.close()
Viewscores=input("Do you want to see previous scores? Y/N")
if Viewscores=="Y":
Classresults=input("Which Class would you like to see the results of?")
else:
print ("Thank you for using the maths quiz, press enter to close the program in 10 seconds")
time.sleep(10)
closeprogram=input("Hit enter")
if Classresults=="A":
ClassA=open("Class A Results.txt","r")
Class=Class
alphabet=ClassA.readlines()
for line in sorted(alphabet):
print(line)
elif Classresults=="B":
ClassB=open("Class B Results.txt","r")
Class=ClassB
alphabet=ClassB.readlines()
for line in sorted(alphabet):
print(line)
elif Classresults=="C":
ClassC=open("Class C Results.txt","r")
Class=ClassC
alphabet=ClassC.readlines()
for line in sorted(alphabet):
print(line)
else:
print ("That is not valid")
sorted's key function can do this for you, but it's much nicer if you haven't combined them into a single string, but store tuples of the pairs instead. Using operator.itemgetter generalizes nicely. Instead of storing:
score = str(score)
Info = Name + " " + score
store:
Info = (Name, score) # Score remains a float
Then when you need to sort, do:
# Imports at top of file, not each sort
from operator import itemgetter
...
for name, score in sorted(myunorderedinfo, key=itemgetter(1, 0)):
In the code you provided, you're writing to a file and reading back (which would require reparsing), so you may want to look at the csv module to store the pairs with proper formatting (simple space separation is easy to mess up); you'd have to convert the inputs back to float in that case though, since csv.reader passes back lists of str, but that's relatively easy to do with a simple generator expression (left as an exercise).
As an aside, you could make your code much neater by removing all that duplicated code:
VALID_CLASS_NAMES = {"A", "B", "C"}
if Classresults not in VALID_CLASS_NAMES:
print("Invalid class results selection")
raise Exception("BOOM")
filename = "Class {} Results.txt".format(Classresults)
with open(filename, "r") as class_results_file:
alphabet=class_results_file.readlines()
for line in sorted(alphabet):
print(line)
Now if you ever add class "D" then you just need to add it to the set of valid class names.
OK so I have this task at school, I'm a complete beginner but I have most of it down, I need to ask for the number and have it output the corresponding name (it's part "d") I managed to get part C to work but when I try to do the same thing to D it refuses to work. I know I'm probably doing something wrong but as I said I'm a complete beginner.
Also, can I tried changing my c+d to "if" so that I could add another "else" so that if the name/number that was input wasn't in any of the lists that it would return saying "invalid" but I cant seem to be able to change them to if statements.
Anyway here's the code I'm trying to make work, like I said, C works but D refuses to:
flag="F"
choice=""
#Looping-----------------------------------------------------------------------
while choice != "F" and choice !="f":
print( " A. Setup Name, Number and CallsPerDay \n"
" B. Display all names and numbers \n"
" C. Insert name to find out number \n"
" D. Insert number and find out name \n"
" E. Display Min, Max and Average CallsPerDay \n"
" F. Finish the Program")
choice=input("Select an option: \n\n")
#Selection---------------------------------------------------------------------
if choice=="A" or choice =="a":
if flag=="F":
names=["gordon", "david", "graeme", "joyce", "douglas", "brian", "suzanne", "karen"]
numb=[273429, 273666, 273512, 273999, 273123, 273224, 273324, 273424]
CPD=[30, 10, 15, 2, 5, 1, 3, 6]
length=len(numb)
print("Names, Numbers and CallsPerDay have now been set up \n")
flag="T"
elif flag=="T":
print("Lists already set up \n")
#---------------------------------------------------------------------------------
elif choice=="B" or choice=="b":
if flag=="F":
print('Run option A first!')
else:
for i in range(0,length,1):
print(names[i],numb[i], CPD[i], "\n")
#-------------------------------------------------------------------------------
elif choice=="C" or choice=="c":
if flag=="F":
print('Run option A first!')
else:
wanted=input('Name please ').lower()
i=0
while names[i] != wanted:
i=i+1
print('Number',numb[i])
#----------Part that refuses to work------------------------
elif choice=="D" or choice=="d":
if flag=="F":
print('Run option A first!')
else:
wanted=input('Number Please: ')
i=0
while numb[i] != wanted:
i=i+1
print('Number',names[i])
Here is the error I get in the shell when trying to do this:
A. Setup Name, Number and CallsPerDay
B. Display all names and numbers
C. Insert name to find out number
D. Insert number and find out name
E. Display Min, Max and Average CallsPerDay
F. Finish the Program
Select an option:
a
Names, Numbers and CallsPerDay have now been set up
A. Setup Name, Number and CallsPerDay
B. Display all names and numbers
C. Insert name to find out number
D. Insert number and find out name
E. Display Min, Max and Average CallsPerDay
F. Finish the Program
Select an option:
d
Number Please: 223666
Traceback (most recent call last):
File "G:\Lvl 5\sofware\menuNEWex - Copy.py", line 62, in <module>
while numb[i] != wanted:
IndexError: list index out of range
>>>
It should be outputting David, because they are both #2 on their lists
There's a few problems here. First, you need to convert wanted from a string to an integer so your comparison will work:
# Not this, because the return of input is a string
wanted=input('Number Please: ')
# But this. Note this will throw a ValueError if converting to an int fails!
wanted = int(input('Number please: '))
# This one has error handling!
try:
wanted = int(input('Number please: '))
except ValueError:
print("That's not a number")
Also, if your entered number is not in your list numb, your loop will still break when i becomes larger than the last index. Try using the index method instead, as it will either return the index of the number or throw a ValueError. Be careful though - that index is the first index of the element in the list. If the same number is repeated, you'll need another approach that handles conflicts:
try:
i = numb.index(wanted)
print('Number', names[i])
except ValueError:
print("No such number")
You should also consider wrapping your input requests in while loops that look for valid values. For example, you need a number for the above section:
i = None
while i is not None:
try:
i = int(input("Number: "))
except ValueError:
# i is still None
print("Must enter a number!")
An example running would give you this:
Number: a
Must enter a number!
Number: b
Must enter a number!
Number: 33
If you put checking your index in that loop, you get checking for integers and valid values at the same time.
I'm having issues with this part of my code:
if(input not in status_list):
print("Invalid Entry, try again.")
break
The break exits the whole program, I just want to go back to the beginning of the program (to while(1):) I've tried pass, continue, return can't think of anything else.. can anyone help??
Thanks :)
Also it's reading this variable income as a string still..: income = int(input("Enter taxable income: ")) The error message I get is "TypeError: 'str' object is not callable"
import subprocess
status_list = ["s","mj","ms","h"]
while(1):
print ("\nCompute income tax: \n")
print ("Status' are formatted as: ")
print ("s = single \n mj = married and filing jointly \n ms = married and filing seperately \n h = head of household \n q = quit\n")
input = input("Enter status: ")
if(input == 'q'):
print("Quitting program.")
break
if(input not in status_list):
print("Invalid Entry, try again.")
break
income = int(input("Enter taxable income: "))
income.replace("$","")
income.replace(",","")
#passing input to perl files
if(input == 's'):
subprocess.call("single.pl")
elif(input == 'mj'):
subprocess.call("mj.pl", income)
elif(input == 'ms'):
subprocess.call("ms.pl", income)
else:
subprocess.call("head.pl", income)
input = input("Enter status: ")
You rebind the name input from the input function to its result, which is a string. So the next time you call it, after continue does its work, input doesn't name a function any more, it's just a string, and you can't call a string, hence
TypeError: 'str' object is not callable
Use continue, and change your variable name so as not to clobber the function.
Your problem isn't continue, it's that you have an unresolved error further down in your code. Continue is doing exactly what it's supposed to (i.e. you want continue in that conditional).
You're renaming input as a string, so the name no longer points to the builtin input function in your code. This is why you don't use reserved keywords as variable names. Call your variable something other than "input" and your code should work fine.
Continue is working correctly. The problem with your script is that you're trying to call replace() on an int:
income = int(input("Enter taxable income: "))
# income is an int, not a string, so the following fails
income.replace("$","")
You can do something like this instead:
income = int(input("Enter taxable income: ").replace("$", "").replace(",", ""))