Why won't my WHILE loops run in Python? - python

I'm a beginner programmer, learning in Python, but I was pretty sure I had a decent grasp of how to make most things run, until I came across this. As i was attempting to run a piece of code with an if..then statement nested inside, Python decided to throw me a curve ball by not running the if...then statements. When I try to run the program, all it does is continually run the one line of code I have inside the while loop, coming before the if...then statement.
Here's the code:
def deg_or_rad():
global deg_rad
deg_rad = False
while deg_rad == False:
query = raw_input("Are you working in 'degrees' or 'radians'? > ").lower
if query == "deg" or \
query == "degrees":
deg_rad = "deg"
print "Cool! I like degrees."
elif query == "rad" or \
query == "radians":
deg_rad = "rad"
print "Cool! I like radians."
else:
"Umm... I'm confused..."
I've tried a few other variables for the while loop, such as:
def deg_or_rad():
global deg_rad
deg_rad = False
while_variable = True
while while_variable == True:
query = raw_input("Are you working in 'degrees' or 'radians'? > ").lower
if query == "deg" or \
query == "degrees":
deg_rad = "deg"
print "Cool! I like degrees."
while_variable = False
elif query == "rad" or \
query == "radians":
deg_rad = "rad"
print "Cool! I like radians."
while_variable = False
else:
"Umm... I'm confused..."
Anyone have any ideas? I'm really confused by this point.

First, in this line:
query = raw_input("Are you working in 'degrees' or 'radians'? > ").lower
you're not calling the .lower() method, because there are no (). You're just setting query equal to the lower method of strings, so you're always taking the else branch.
Second, in this line:
"Umm... I'm confused..."
You're not printing anything, you just made a string. So even though that branch is being taken, you're not doing anything you can see.

This is a combination of two things that make it seem like nothing is happening.
To lower a string, you do s.lower(), not s.lower. s.lower is a method.
What you're doing is you're assigning that method to query. So, none of the ifs will ever match. This means the else branch is executed. But, you don't print "Umm... I'm confused...", you just have the string itself there. This leads to you not getting any output.

couple of things
lower is a function call, you should use it like lower()
You are not printing the string in the else: statement. So it appears like nothing is happening even though you are getting here. This is because that function itself will not match your previous conditions (the results of the function may)
Don't say while_variable == True or deg_rad == False just use while_variable or not deg_rad respectively. (This isn't really part of the problem, just bad style.)
You could trying printing things to try and debug where your function is deviating from expected behavior to try and narrow it down. For instance if you put in a debug print just after you capture query input you could see that it wasn't what you were hoping for.
example:
def deg_or_rad():
global deg_rad
deg_rad = False
while not deg_rad:
query = raw_input("Are you working in 'degrees' or 'radians'? > ").lower()
if query in ("deg", "degrees"):
deg_rad = "deg"
print "Cool! I like degrees."
elif query in ("rad", "radians"):
deg_rad = "rad"
print "Cool! I like radians."
else:
print "Umm... I'm confused..."

raw_input("Are you working in 'degrees' or 'radians'? > ").lower
You haven't called the lower method, so at this point query is always going to be a bound method object (something along the lines of <built-in method lower of str object at 0x1001a0030>).
Furthermore, in your else clause you have not used print, so the string is created then thrown away without being displayed.
Thus you get the raw_input, then nothing.

Related

Is there an alternative to .endswith()?

I am trying to write an if, elif else clause, so that depending on the German word ending, we can see is it should go with der, die or das.
Here is my code:
word = input ("Enter word: ")
if (word.endswith('er' 'ismus')):
print ("der")
elif (word.endswith('falt' 'heit' 'keit' 'schaft' 'ung')):
print ("die")
else (word.endswith('chen' 'lein')):
print ("das")
I have also tried using suffix with square brackets but everything goes grey when I do that and so I can assume it won't work. And clearly true and false are not adequate responses for what I need. Is there anything else I can try?
Thanks in advance!
The endswith method really only checks if the word ends with one thing, but you can do something like:
def word_ends_with_one_of(word, options):
for option in options:
if word.endswith(option):
return True
return False
Then call that with:
suffix_die = ['falt', 'heit', 'keit', 'schaft', 'ung']
suffix_der = ['er', 'ismus']
suffix_das = ['chen', 'lein']
if word_ends_with_one_of(word, suffix_die):
print ("die")
elif word_ends_with_one_of(word, suffix_der):
print ("der")
elif word_ends_with_one_of(word, suffix_das):
print ("das")
As an aside, your else clause is currently problematic, it should not have a condition attached to it (unless it's a typo and you meant to have an elif instead).
Now, even though that you be a useful function to have for other purposes, you may want to consider a more application focused method since you'll be introducing a function anyway. By that, I mean something more closely suited to your specific needs, such as:
def definite_article_for(word):
# Could also use word_ends_with_one_of() in here.
if word.endswith('er'): return 'der'
if word.endswith('ismus'): return 'der'
if word.endswith('falt'): return 'die'
:
if word.endswith('lein'): return 'das'
return None
}
Then use article = definite_article_for(my_word) to get the article you want.

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 does my return statement ignore the rest of my code in a function in python?

In my function, I type in a raw_input after my return statement and then I proceed to call my function. When I call my function the raw_input is totally ignored and only the return statement works.
def game():
#This selects 5 community cards from the pick_community function
community = pick_community(5)
card_4 = community[3]
card_5 = community[4]
first_3 = community[0:3]
return first_3
river = raw_input("If you are done with the round hit enter:" )
try:
if river =="":
return card_4
except:
print "Dont cheat man"
exit()
That:
return first_3
returns and therefore ends the function.
The remaining code is just ignored, because you will never get past the return.
Because a return statement gets out of the function, so the rest of the code wont execute
If you want to return first 3 values and then continue in code you can do it using yield. It basically inserts values into generator, then in the end return the whole generator.
https://pythontips.com/2013/09/29/the-python-yield-keyword-explained/
more here, or google for even more :)

Trying to return a True variable from a nested chain of functions (in Python)...

I'm trying to write part of an adventure game program in Python, and though I have most of it down, I'm stuck at trying to return a value declared as "True" at the end of one branch in the function chain. Basically, this is a fight against a monster, which you can win if you choose the right options. If you win, you obtain the bow that he was guarding. Here is the code of the fight:
#The first line imports all the text displayed in the game, saved in gametext.py
#For purposes of clarity, all text has been saved to variables imported by the file.
#Any variable that is not "HaveBow", "why" or declared by a raw_input() is actually text.
from gametext import *
def BG_fight():
print BowGuardIntro
print InitOptions
BGfirstmove = raw_input('> ')
if BGfirstmove == "1":
spearfight()
elif BGfirstmove == "2":
dead(BGUnarmed1)
else:
dead(BGUnarmed2)
def spearfight():
print GotSpear
print SpearFight
spearact = raw_input("> ")
if spearact == "1":
blindfight()
elif spearact == "2":
dead(SeeChest)
elif spearact == "3":
dead(SeeArms)
else:
dead(NoUseSpear)
def blindfight():
print BlindFight
followblow = raw_input("> ")
if followblow == "1":
print Victory
HaveBow = True
return HaveBow
elif followblow == "2":
dead(BlindArms)
else:
dead(BlindNoKill)
def dead(why):
print why
exit(0)
BG_fight()
(If people are interested, I can also produce the contents of the gametext file, though I would rather not as it is lengthy and has nothing to do with the problem I'm having)
As you can see, only one branch there offers the winning condition (which would give the HaveBow = True value that I want to return), and it is nested two functions deep and part of an if-statement. What I want to know is how I return that "HaveBow = True" value back outside the function chain, so it can be used in other parts of the game? If I try to code:
HaveBow = blindfight()
print HaveBow
at the end of the code and try to run it, it just makes me repeat that part of the game twice, before declaring "True". Same goes if I try BG_fight() instead of blindfight(). But I don't want that; I just want the "True" for "HaveBow" so I can use the condition "HaveBow = True" in other parts of the game.
In short, my question is whether or not it's possible to return a value from a nested function chain without repeating the code of that chain, and if so, how?
Thanks.
You can only return a value, not a name and a value. In other words, you cannot "return HaveBow = True"; all you can do is return True. There's no way to return a value and at the same time assign it to a variable that exists outside the function. If you want to assign the value, you need to do it outside the function.
From what you say, it sounds like you want HaveBow to be a global variable that you can use anywhere in your program. In that case, you can change your code in blindfight to do:
if followblow == "1":
global HaveBow
print Victory
HaveBow = True
Note that in this case you do not need to return the True value -- you just directly assign it to a global variable.
Ultimately there are better ways to structure your code, but those issues are out of the scope of this question. For the moment, I would suggest that, if you have global state like HaveBow that you want to be able to use "anywhere else in the game", you should make those global variables using global as I showed in my example. As you progress learning more programming, you will gradually learn why using global variables is not usually the best idea, but for the purposes of this program it is the simplest solution.

Python loop controler continue is not working properly

As I know, "continue" will jump back to the top of the loop. But in my case it's not jumping back, continue don't like me :(
for cases in files:
if ('python' in cases.split()):
execute_python_scripts(cases.split())
elif run_test_case(cases.split()):
continue
else:
logger("I am here")
break
In my case run_test_case() gives 1, 2, 3, 4 etc... But it always performs first(1) and jump to the else part. So I am getting the "I am here" message. It should not work like this. As I am using "continue", it should jump to the for loop.
Following is the run_test_case():
def run_test_case(job):
for x in job:
num_of_cases = num_of_cases - 1
test_type = x.split('/')
logger(log_file,"Currently "+ x +"hai!!")
if test_type[0] == 'volume':
backdoor = test_type[1].split("_")
if backdoor[0] == 'backdoor':
return get_all_nas_logs()
else:
if perform_volume_operations(x,num_of_cases) == False:
return False
else:
logger(log_file,"wrong ha!!")
Why is it always going to the else part, without jumping back to the for loop? Thanks in advance.
Here elif run_test_case(cases.split()): you are calling the run_test_case method, that will run your code to evaluate the result for the elif condition.
It only enters the block delimited by elif (in your case, continue), if the result of that method evaluates to True, otherwise it will jump to the else clause.
The problem is probably in your run_test_case code, that is never returning True, and so you'll never get the behavior that you're expecting.
It's hard to say without knowing exactly what you want to accomplish, but I'd say that you're missing a return True in the end of that code, meaning, if everything executes correctly right until the end, you want it to return True... but I'm only guessing here, you need to think about what that method is supposed to do.
In python an if or elif clause is evaluated for not only the True and False constants, but more generally for True-like and False-like values. None, for instance, is a false-like value, a non-empty string is a true-like value, etc.
Check this from the documentation on values that are considered true or false:
http://docs.python.org/library/stdtypes.html

Categories