NameError: global name 'PIN' is not defined - python

I am getting the following Error Message :
Traceback (most recent call last):
File "/Volumes/KINGSTON/Programming/Assignment.py", line 17, in <module>
Assignment()
File "/Volumes/KINGSTON/Programming/Assignment.py", line 3, in Assignment
My code is:
def Assignment():
prompt = 'What is your PIN?'
result = PIN
error = 'Incorrect, please try again'
retries = 2
while result == PIN:
ok = raw_input(Prompt)
if ok == 1234:
result = menu
else:
print error
retries = retries - 1
if retries < 0:
print 'You have used your maximum number of attempts. Goodbye.'
Assignment():
would really appreciate a little help if anyone knows where i am going wrong and can explain

That particular error is raised because when you say result = PIN, PIN doesn't actually exist. Since it isn't in quotes, Python assumes it is a variable name, but when it goes to check what that variable is equal to, it doesn't find anything and raises the NameError. When you fix that, it will also happen with prompt since you later refer to it as Prompt.
I'm not sure if this is your full code or not, so I'm not sure what the other issues could be, but it looks like you are using result and PIN to control your while loop. Remember that a while loop runs until the condition it is checking is False (or if you manually break out of it), so instead of declaring the extra variables, you could start with something like this:
def Assignment():
# No need to declare the other variables as they are only used once
tries = 2
# Go until tries == 0
while tries > 0:
ok = raw_input('What is your PIN?')
# Remember that the output of `raw_input` is a string, so either make your
# comparison value a string or your raw_input an int (here, 1234 is a string)
if ok == '1234':
# Here is another spot where you may hit an error if menu doesn't exist
result = menu
# Assuming that you can exit now, you use break
break
else:
print 'Incorrect, please try again'
# Little shortcut - you can rewrite tries = tries - 1 like this
tries -= 1
# I'll leave this for you to sort out, but do you want to show them both
# the 'Please try again' and the 'Maximum attempts' messages?
if tries == 0:
print 'You have used your maximum number of attempts. Goodbye.'

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)

If/Elif/Else Statement in Python - Else Statement prints even though the if constraints are being met

I am in my first month of programming and I have encountered an issue in an app I'm developing. I'm sure it's fairly simple for someone experienced but I don't know how to fix it without a syntax error. Here's my code (see below for output error)
def what_to_find():
find = (input(": "))
if find == int(1):
find_slope()
elif find == int(2):
find_elevation1()
elif find == int(3):
find_elevation2()
else:
print("Choose a number corresponding to what you want to find")
what_to_find()
So the input function works, but regardless of what number I put in (either 1, 2, or 3), the 'print' under the else command always prints. Here is what the output is for example:
What are you trying to find?
1 = Slope, 2 = Higher Elevation, 3 = Lower Elevation
: 1
Choose a number corresponding to what you want to find
Insert higher elevation:
So I have more code after this which creates the prompt for the higher elevation, but I just want to know how to make sure it doesn't print the else statement once it runs. Also I am using Visual Studio Code for my IDE.
From a very inexperienced coder, thanks in advance for your help!
UPDATE: After revising and using input from others, this is what I have:
def what_to_find():
find = int(input(": "))
if find == 1:
find_slope()
elif find == 2:
find_elevation1()
elif find == 3:
find_elevation2()
else:
print("Choose a number corresponding to what you want to find")
what_to_find()
Which all made sense, put this becomes the output (after I plug in one of the corresponding numbers of the if statement):
What are you trying to find?
1 = Slope, 2 = Higher Elevation, 3 = Lower Elevation
: 1
Traceback (most recent call last):
File "gcalc.py", line 24, in <module>
what_to_find()
File "gcalc.py", line 15, in what_to_find
find_slope()
NameError: name 'find_slope' is not defined
Not sure how this occurred or why the change to the beginning 'find' made this output. Please help me out! Thanks
To eliminate the overhead of doing int(find) on each of the if statements, just implement the required condition on the initial user input so like this:
find = int(input(": "))
and then each if statement can be just checking for the value like this:
if find == 1:
#run this scope
etc etc...

can't get program to iterate properly (TypeError: 'NoneType' object is not iterable)

So just getting started learning python. as practice i decided to build a program that would handle my attacks for my D&D character and i can't quite seem to get this to iterate properly.
from random import randint
def roll_dice():
type = raw_input("Initiative (i) or Attack (a): ") #variable that is passed through the function
roll = randint(1,20)
if roll == 1:
print "Natural 1"
elif roll == 20:
print "Natural 20"
else:
crit = "n"
if type == 'i':
result = roll + 5
print "Initiative = %d" % result
return
elif type == 'a':
""" most of the rest of the program is after here but that all works fine so there is no reason to take up space with that"""
roll_dice()
for type in roll_dice():
if type == 'a' or type == 'i':
continue
program will loop once and then gives me:
TypeError: 'NoneType' object is not iterable
I know this means that the second time it goes to iterate it is passing nothing through but i can't quite figure out how to fix it.
any help and/or explanations would be greatly appreciated
Edit:
I know it does not run as posted. The whole thing is over 100 lines and I did not want to swamp people with that. Once I get home I will post with the whole thing.
For clarification: With the whole program it will run once through loop back to the start and then return the error after a completed second run through the program. So the first time through the loop works it is after the completed second run and attempting to start a third.
It doesn't seem like your roll_dice() function returns anything, causing the TypeError. The reason it "seems" like the program loops once is because of the line right before the for loop, which calls the function.
What it seems like you are trying to do is extract the type variable from inside your function, which can be done by returning the type with return type instead of just return and using the if statement alone. To loop until type isn't a or i, a while loop may be more useful, like so:
while True:
type = roll_dice()
if type != 'a' and type != 'i':
break

Why is this function creating an infinite loop?

Why is this creating an infinite loop? And if it isn't creating one, why does the program freeze up? Not like IDLE stops responding, It just stops like I created a infinite loop and the only thing it does is input(). Try the code out to see what I mean.
(also, tell me if the for's are correct in the comments please)
Accounts = {}
def create_account(x,y,z,a):
global Accounts
Checked = False
while Checked == False:
if x in Accounts:
print("Sorry, that name has already been taken")
print("Please choose a new name")
x = input()
for dictionary in Accounts:
for key in dictionary:
if a in key:
print("Sorry, password is invalid or not avalible")
print("Please choose a new password")
a = input()
Accounts[x] = {"Proggress":y,"Points":z,"Pass":a}
print(Accounts[x])
Your code creates an infinite loop because there is nothing to stop it.
while checked == False will do exactly what it sounds like, it will loop over the code over and over until checked = True OR until you break
break will simply stop the loop, allowing the program to finish.
checked = True will also stop the loop
I think that what you are trying to do is something like this:
This code is untested
Accounts = {}
def create_account(x,y,z,a):
global Accounts
Checked = False
while Checked == False:
if x in Accounts:
print("Sorry, that name has already been taken")
print("Please choose a new name")
x = input()
else:
passwordOk = True
for dictionary in Accounts:
for key in dictionary:
if a in key:
passwordOk = False
break
if not passwordOk:
break
if not passwordOk:
print("Sorry, password is invalid or not avalible")
print("Please choose a new password")
a = input()
else:
Checked = True # this is the important part that you missed
Accounts[x] = {"Proggress":y,"Points":z,"Pass":a}
print(Accounts[x])
Just for you to know, your code can be optimized. I tried to solve your issue by modifying as minimum code as possible, so that you could understand the problem
There are two issues causing this.
As you say,
the print() is before the input(), and the print never outputs, so it doesn't get that far
However, let's take a step back: the print statements are inside the block if x in Accounts:. At the very first line, you set Accounts to be an empty dictionary (Accounts = {}), so no matter what x is, at that point, x in Accounts will never be true - there's nothing in it.
Now, you do have a line that adds items to Accounts:
Accounts[x] = {"Proggress":y,"Points":z,"Pass":a}
However, as other people have pointed out, you'll never get here - it's outside the loop, and the loop never exits because Checked is never set to True, nor is a break called.
Your program then is essentially just going through the same few steps that don't do anything:
Does Checked == False? Yep, continue the loop.
Is x in Accounts? Nope, skip this block.
For every dictionary in Accounts, do some stuff, but Accounts is empty, so I don't need to do anything.
Does Check == False? Yep, continue the loop.

NameError when programming in 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")

Categories