NameError when programming in python - python

I made a program in python that is supposed to accept a name as user input. It will then check if the name given is contained inside a string that is already given and if it is then the program will print out the telephone next to that name. My code is as follows:
tilefwnikos_katalogos = "Christoforos 99111111: Eirini 99556677: Costas 99222222: George 99333333: Panayiotis 99444444: Katerina 96543217"
check=str(input("Give a name: "))
for check in tilefwnikos_katalogos:
if check=="Christoforos":
arxi=check.find("Christoforos")
elif check=="Eirini":
arxi=check.find("Eirini")
elif check=="Costas":
arxi=check.find("Costas")
elif check=="George":
arxi=check.find("George")
elif check=="Panayiotis":
arxi=check.find("Panayiotis")
elif check=="Katerina":
arxi=check.find("Katerina")
s=check.find(" ",arxi)
arxi=s
y=check.find(":",arxi)
telos=y
apotelesma=tilefwnikos_katalogos[arxi+1:telos]
print(apotelesma)
But when I try to run it, I input the name and then the following message pops up:
Traceback (most recent call last):
File "C:\Users\Sotiris\Desktop\test.py", line 16, in <module> s=check.find(" ",arxi)
NameError: name 'arxi' is not defined
What am I doing wrong?

You're getting your error because arxi isn't getting defined in the first place when then name the user gave is not present on your list.You can fix that by simply adding an unconditional else case to your if/else if bundle as pointed in the comments. But the very way you tackled this problem is faulty, storing data like this in a string is a bad idea, you want to use a dictionary:
phone_catalog = {'Christoforos': 99111111, 'Eirini': 99556677, 'Costas': 99222222, 'George':99333333, 'Panayiotis':99444444, 'Katerina': 96543217}
Also check isn't a very clear variable name, maybe you should try using something better like:
user_name = str(input("Give a name: "))
And now you can do your if/elif condition but replacing it for using dictionary logic and making sure you have a final else, like such:
if user_name in phone_catalog:
print(phone_catalog[user_name])
else:
print("Unknown user")
See how the dictionary made your life much easier and your code cleaner here? Read more on Python Data Structures.

so there are a few things you have overlooked / not going as expected, the first of which is how iterating over strings in python works:
tilefwnikos_katalogos = "Christoforos 99111111: Eirini 99556677: Costas 99222222: George 99333333: Panayiotis 99444444: Katerina 96543217"
for check in tilefwnikos_katalogos:
print(check)
#print(repr(check)) #this shows it as you would write it in code ('HI' instead of just HI)
so check can never be equal to any of the things you are checking it against, and without an else statement the variable arxi is never defined. I'm assuming you meant to use the check from the user input instead of the one in the loop but I'm not sure you need the loop at all:
tilefwnikos_katalogos = "Christoforos 99111111: Eirini 99556677: Costas 99222222: George 99333333: Panayiotis 99444444: Katerina 96543217"
check=str(input("Give a name: ")) #the str() isn't really necessary, it is already a str.
if check=="Christoforos":
arxi=check.find("Christoforos")
elif check=="Eirini":
arxi=check.find("Eirini")
elif check=="Costas":
arxi=check.find("Costas")
elif check=="George":
arxi=check.find("George")
elif check=="Panayiotis":
arxi=check.find("Panayiotis")
elif check=="Katerina":
arxi=check.find("Katerina")
else: raise NotImplementedError("need a case where input is invalid")
s=check.find(" ",arxi)
arxi=s
y=check.find(":",arxi)
telos=y
apotelesma=tilefwnikos_katalogos[arxi+1:telos]
print(apotelesma)
but you could also just see if check is a substring of tilefwnikos_katalogos and deal with other conditions:
if check.isalpha() and check in tilefwnikos_katalogos:
# ^ ^ see if check is within the string
# ^ make sure the input is all letters, don't want to accept number as input
arxi=check.find(check)
else:
raise NotImplementedError("need a case where input is invalid")
although this would make an input of C and t give Cristoforos' number since it retrieves the first occurrence of the letter. An alternative approach which includes the loop (but not calling the variable check!) would be to split up the string into a list:
tilefwnikos_katalogos = "..."
check = input(...)
for entry in tilefwnikos_katalogos.split(":"):
name, number = entry.strip().split(" ")
if check == name:
apotelesma=number
break
else:
raise NotImplementedError("need a case where input is invalid")
although if you are going to parse the string anyway and you may use the data more then once it would be even better to pack the data into a dict like #BernardMeurer suggested:
data = {}
for entry in tilefwnikos_katalogos.split(":"):
name, number = entry.strip().split(" ")
data[name] = number #maybe use int(number)?
if check in data:
apotelesma = data[check]
else:
raise NotImplementedError("need a case where input is invalid")

Related

trying to simplify some boolean statements in python

I'm "newish" to python programming. I'm trying my best to make my code look nice and function well. I'm using Pycharm as my IDE. I'm doing something for myself. I play tabletop RPG's and I'm attempting to create a character creator for a game I play. I have everything working well, but Pycharm is telling me that "Expression can be simplified" and "PEP 8: E712 comparison to True should be 'if cond is not True:' or 'if not cond:'"
Here is the code in question:
fname = False
while fname != True:
new_character.firstName = input('What would you like your first name to be?\n').capitalize()
if 1 >= len(new_character.firstName) or len(new_character.firstName) > 20:
print('Name does not meet length requirements. Please try again.')
if new_character.firstName.isalpha() != True:
print('Please do not use numbers or special characters in your name. Please try again.')
if (1 < len(new_character.firstName) < 20) and (new_character.firstName.isalpha() == True):
fname = True
Pycharm is telling me that my "while fname != True:" is the part that can be simplified as well as the "if new_character.firstName.isalpha() != True:".
I've tried googling a solution for what I'm doing, but most of them are for something kinda like what I'm asking, but never with the != True portion. I've even reached out to one of my friends that's a python programmer, but I haven't heard back yet.
Again, I want to state that as it is now, the code works correctly the way it is written, I'm just wanting to understand if there is a way to make the code look cleaner/neater or do the same function and be simplified somehow.
Any pointers on how to potentially simplify those lines of code and maintain the functionality would be greatly appreciated.
Here's one way you could rewrite this code to make it easier to read, and more efficient:
# Loop until the user provides a good input
while True:
# Set a temp variable, don't constantly reassign to the new_character.firstName attribute
name = input('What would you like your first name to be?\n').capitalize()
# If the name isn't between 2 and 20 characters, start the loop over at the beginning
if not (1 < len(name) <= 20):
print('Name does not meet length requirements. Please try again.')
continue
# If the name contains anything other than letters, start the loop over at the beginning
if not name.isalpha():
print('Please do not use numbers or special characters in your name. Please try again.')
continue
# You can only reach this break if the name "passed" the two checks above
break
# Finally, assign the character name
new_character.firstName = name
One thing you could do to simplify further is to check both conditions at the same time, and print a more helpful error message that re-states the requirements explicitly:
NAME_ERROR_MESSAGE = """
Invalid name '{name}'. Your character's name
must be between 2 and 20 characters long, and
contain only letters. Please try again.
"""
while True:
name = input('What would you like your first name to be?\n').capitalize()
if (1 < len(name) <= 20) and name.isalpha():
new_character.firstName = name
break
print(NAME_ERROR_MESSAGE.format(name=name)

Need to set a default value for multiple input for list in Python

I'm trying to get the default value if input is blank, how can I do that?
Output what I'm getting is for variable is blank if there is no user input.
Brand_default = 'ABC','XYZ'
cate_default = 'GKK','KKL','MKK','UKK'
Brand = list(input('Please enter Brand? (ABC/XYZ)= ').split(',') or Brand_default)
Cate = list(input('Please enter Category?GKK,KKL,MKK,UKK = ').split(',') or cate_default)
Your logic needs to decide whether the value is empty, and then split if not. Unfortunately, this means your otherwise rather elegant or formulation won't work.
def split_or_default(prompt, default):
response = input(prompt + " (" + "/".join(default) + ") ")
if response == "":
return default
return response.split(",")
Brand = split_or_default(
'Please enter Brand?',
['ABC','XYZ'])
Cate = split_or_default(
'Please enter Category?',
['GKK','KKL','MKK','UKK'])
Notice also how the defaults are also lists now. I suppose your code could work with lists or tuples, but that seems like an unwelcome complication.
Tangentially, you should probably remove the "Please enter" part from the prompt. It's nice to be polite, but in user interfaces, it's actually more friendly to be concise.
Requiring commas between the values is also somewhat cumbersome. If some values could contain spaces, you need for the input to be unambiguous; but if these examples are representative, you could just as well split on whitespace.
In keeping with the DRY Principle I refactored the repeated code into a function.

Nested Loop 'If'' Statement Won't Print Value of Tuple

Current assignment is building a basic text adventure. I'm having trouble with the following code. The current assignment uses only functions, and that is the way the rules of the assignment state it must be done.
def make_selections(response):
repeat = True
while repeat == True:
selection = raw_input('-> ')
for i, v in enumerate(response):
i +=1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
if selection == i:
print v[1]
else:
print "There's an error man, what are you doing?!?!?"
firstResponse = 'You chose option one.'
secondResponse = 'You chose option two.'
thirdResponse = 'You chose option three.'
responses = [(0, firstResponse), (1, secondResponse),( 0, thirdResponse)]
make_selections(responses)
My intention in that code is to make it so if the user selects a 1, it will return firstResponse, if the user selects 2 it will return secondResponse, etc.
I am basically just bug testing the code to make sure it produces the appropriate response, hence the "Error man..." string, but for some reason it just loops through the error message without printing the appropriate response string. Why is this?
I know that this code is enumerating the list of tuples and I can call them properly, as I can change the code to the following and get the expected output:
for i, v in enumerate(response):
i += 1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
print i, v
Also, two quick asides before anyone asks:
I know there is currently no way to get out of this while loop. I'm just making sure each part of my code works before I move on to the next part. Which brings me to the point of the tuples.
When I get the code working, a 0 will produce the response message and loop again, asking the user to make a different selection, whereas a 1 will produce the appropriate response, break out of the loop, and move on to the next 'room' in the story... this way I can have as many 'rooms' for as long of a story as I want, the player does not have to 'die' each time they make an incorrect selection, and each 'room' can have any arbitrary amount of options and possible responses to choose from and I don't need to keep writing separate loops for each room.
There are a few problems here.
First, there's no good reason to iterate through all the numbers just to see if one of them matches selection; you already know that will be true if 1 <= selection <= len(response), and you can then just do response[selection-1] to get the v. (If you know anything about dicts, you might be able to see an even more convenient way to write this whole thing… but if not, don't worry about it.)
But if you really want to do this exhaustive search, you shouldn't print out There is an error man after any mismatch, because then you're always going to print it at least twice. Instead, you want to only print it if all of them failed to match. You can do this by keeping track of a "matched" flag, or by using a break and an else: clause on your for loop, whichever seems simpler, but you have to do something. See break and continue Statements, and else Clauses on Loops in the tutorial for more details.
But the biggest problem is that raw_input returns a string, and there's no way a string is ever going to be equal to a number. For example, try '1' == 1 in your interactive interpreter, and it'll say False. So, what you need to do is convert the user's input into a number so you can compare it. You can do that like this:
try:
selection = int(selection)
except ValueError:
print "That's not a number!"
continue
Seems like this is a job for dictionaries in python. Not sure if your assignment allows this, but here's my code:
def make_selections(response):
selection = raw_input('-> ')
print response.get(selection, err_msg)
resp_dict = {
'1':'You chose option one.',
'2':'You chose option two.',
'3':'You chose option three.'
}
err_msg = 'Sorry, you must pick one of these choices: %s'%sorted(resp_dict.keys())
make_selections(resp_dict)
The problem is that you are comparing a string to an integer. Selection is raw input, so it comes in as a str. Convert it to an int and it will evaluate as you expect.
You can check the type of a variable by using type(var). For example, print type(selection) after you take the input will return type 'str'.
def make_selections(response):
repeat = True
while repeat == True:
selection = raw_input('-> ')
for i, v in enumerate(response):
i +=1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
if int(selection) == i:
print v[1]
else:
print "There's an error man, what are you doing?!?!?"

get the list and input from one function and run them in different function

i have a programm that generate the list and then i ask them to tell me what they want to do from the menu and this is where my problem start i was able to get the input form the user to different function but when i try to use the if else condition it doesn't check, below are my code
def menu(x,l):
print (x)
if x == 1:
return make_table(l)
if x == 2:
y= input("enter a row (as a number) or a column (as an uppercase letter")
if y in [ "1",'2','3']:
print("Minmum is:",minimum(y,l))
if x== 3:
print ('bye')
def main():
bad_filename = True
l =[]
while bad_filename == True:
try:
filename = input("Enter the filename: ")
fp = open(filename, "r")
for f_line in fp:
f_str=f_line.strip()
f_str=f_str.split(',')
for unit_str in f_str:
unit=float(unit_str)
l.append(unit)
bad_filename = False
except IOError:
print("Error: The file was not found: ", filename)
#print(l)
condition=True
while condition==True:
print('1- open\n','2- maximum')
x=input("Enter the choice")
menu(x,l)
main()
from the bottom function i can get list and i can get the user input and i can get the data and move it in second function but it wont work after that.thank you
I think your problem is simple, and has nothing to do with how you're passing values between functions.
In main, you're reading a value from the user like this:
x=input("Enter the choice")
The input function:
… reads a line from input, converts it to a string (stripping a trailing newline), and returns that.
So, if the user types 1 at the prompt, you get back the string "1".
Now, you pass that value—perfectly correctly—to menu.
In menu, you then try to compare it to various numbers, like this:
if x == 1:
But this will never be true. A string, like "1", is never equal to a number, like 1. They're not even the same kind of value, much less the same value.
So, you need to do one of two things:
Convert the input to an number. For example, change menu(x,l) to menu(int(x), l). OR…
Write menu to expect strings. For example, change if x == 1: to if x == "1":.
You may be wondering why that print (x) didn't help you debug the problem.
print(x) prints out the end-user-friendly string representation of whatever you give it. That is, it automatically calls the str function for you. For debugging purposes, you often want to use repr instead of str, to get the programmer-friendly string representation instead of the end-user-friendly string representation.
For example, print(str("10")) will print out 10—just like print(str(10)), so you can't tell them apart. But print(repr("10")) will print out '10', unlike print(repr(10)), while prints 10, so you can tell them apart. repr can also help you spot things like strings with invisible characters in them, having special "node" objects from a parser instead of just strings, etc.

Python - display different output if the input is a letter or a number

I want to print the result of the equation in my if statement if the input is a digit and print "any thing" if it is a letter.
I tried this code, but it's not working well. What is wrong here?
while 1:
print '\tConvert ciliuse to fehrenhit\n'
temp = input('\nEnter the temp in C \n\t')
f = ((9/5)*temp +32)
if temp.isdigit():
print f
elif temp == "quit" or temp == "q" :
break
elif temp.isalpha() :
print ' hhhhhhh '
You need to go through your code line by line and think about what type you expect each value to be. Python does not automatically convert between, for example, strings and integers, like some languages do, so it's important to keep types in mind.
Let's start with this line:
temp = input('\nEnter the temp in C \n\t')
If you look at the documentation for input(), input() actually calls eval() on what you type in in Python 2.x (which it looks like you're using). That means that it treats what you type in there as code to be evaluated, just the same as if you were typing it in the shell. So if you type 123, it will return an int; if you type 'abc', it will return a str; and if you type abc (and you haven't defined a variable abc), it will give you an error.
If you want to get what the user types in as a string, you should use raw_input() instead.
In the next line:
f = ((9/5)*temp +32)
it looks like you're expecting temp to be a number. But this doesn't make sense. This line gets executed no matter what temp is, and you're expecting both strings containing digits and strings containing letters as input. This line shouldn't go here.
Continuing on:
if temp.isdigit():
isdigit() is a string method, so here you're expecting temp to be a string. This is actually what it should be.
This branch of the if statement is where your equation should go, but for it to work, you will first have to convert temp to an integer, like this:
c = int(temp)
Also, to get your calculation to work out right, you should make the fraction you're multiplying by a floating-point number:
f = ((9/5.0)*c +32)
The rest of your code should be okay if you make the changes above.
A couple of things first - always use raw_input for user input instead of input. input will evaluate code, which is potentially dangerous.
while 1:
print "\tConvert ciliuse to fehrenhit\n"
temp = raw_input("\nEnter the temp in C \n\t")
if temp in ("quit", "q"):
break
try:
f = ((9.0 / 5.0) * float(temp) + 32)
except ValueError:
print "anything"
Instead of using isalpha to check if input is invalid, use a catch clause for ValueError, which is thrown when a non-numerical value is used.
Why isn't it working? Are you getting an error of any kind?
Straight away I can see one problem though. You are doing the calculation before you verify it as a number. Move the calculation to inside the if temp.isdigit().
Take a look at this for some examples:
http://wiki.python.org/moin/Powerful%20Python%20One-Liners
OK, this works. Only problem is when you quit, you get dumped out of the interpreter.
while 1: import sys; temp=raw_input('\nEnter the temp in C \n\t'); temp.isdigit() and sys.stdout.write('%lf' %((9./5)*float(temp)+32)) or temp=='q' and sys.exit(0) or sys.stdout.write(temp)

Categories