I am trying to build something simple from a book that I have. I want it to only accept one of two inputs, either Clockwise or Counterclockwise. However, the program enters the while loop even while they type Clockwise or Counterclockwise. Is there a way I can fix this?
import turtle
Spin = input("Clockwise or Counterclockwise?")
while Spin != "Clockwise" or Spin != "Counterclockwise":
print("Please Try Again")
Spin = {input("Clockwise or Counterclockwise?")}
x = input(str("Put in desired Length:"))
SideLength = int(x)
def drawSideAndTurn(SideLength):
turtle.forward(SideLength)
if Spin == "Clockwise":
turtle.right(90)
if Spin == "Counterclockwise":
turtle.left(90)
y = (input("Number of Sides:"))
n = int(y)
x = 1
while x <= n:
drawSideAndTurn(SideLength)
drawSideAndTurn(SideLength)
x += 1
SideLength += 10
I'm not really sure how to define it so that Spin could be equal to the string input of a user.
The issue isn't in the value in String; the issue is in the Boolean condition you're expressing.
Your while loop is framed as follows:
while Spin != "Clockwise" or Spin != "Counterclockwise":
print("Please try again!")
Let's walk through the evaluation for arbitrary inputs.
Suppose your user enters Clockwise.
Spin != "Clockwise" will evaluate to False
Spin != "Counterclockwise" is equivalent to "Clockwise" != "Counterclockwise", which is True
while False or True is while True, so the body of the while loop will evaluate.
Suppose instead your user enters Counterclockwise.
Spin != "Clockwise" will evaluate to True.
while True or [...] is while True, so the body of the while loop will evaluate (Python evaluates Boolean conditions lazily, so it won't even bother testing the part of the expression to the right of the or; see here).
If you want to validate the input to ensure it's in one of two values (Clockwise or Counterclockwise) you need to check something like:
while not (Spin == "Clockwise" or Spin == "Counterclockwise"):
...
or:
while Spin != "Clockwise" and Spin != "Counterclockwise"):
...
You can express this condition more concisely as:
while Spin not in ("Clockwise", "Counterclockwise"):
...
Better yet, if the set of inputs is known and reasonably fixed, you can write something like this:
from enum import Enum
class Spin(Enum):
CLOCKWISE = "clockwise"
COUNTERCLOCKWISE = "counterclockwise"
def __str__(self):
return self.value
input_spin = input("Enter direction of spin:")
# Loosely normalize input_spin so that "ClockwiSe "
# is treated like a valid input for "clockwise".
while not input_spin.strip().lower() in map(str, Spin):
...
Just change “or” to “and”. The input can’t be both be “clockwise” and “counter clockwise” at the same time, that’s why it never exits the while loop.
Related
I have a for loop that I'm needing to break if there is an error.
I want to be able to continue a for loop if a boolean is true. But don't want to have to write an "if" statement over and over again. Is it possible to call "continue" outside of a "loop"?
The following code results in an error. But is my thinking of this would work.
_Range = 6
_RangeEnd = 0
def function_to_call():
print("x")
if _Continue is True:
continue
for x in range(_Range):
_RangeEnd = _RangeEnd + 1
function_to_call()
if _RangeEnd == 5:
_Continue = True
If this isn't possible. What would be an efficient way to do this? I'm reusing this function in a good number of different for loops.
You can't call continue outside of a loop, e.g. from a function called from inside a loop.
One option is to return a meaningful value from your function that tells the caller to continue, i.e. some truthy value or falsy value:
def function_that_decides_to_continue():
print("x")
return your_condition_here
for x in range(_Range):
if function_that_decides_to_continue():
continue # skip extra stuff
# do extra stuff
Or a sentinel object:
CONTINUE = object() # sentinel object, whose sole purpose is to be uniquely identifiable
def function_that_decides_to_continue():
print("x")
if your_condition_here:
return CONTINUE
for x in range(_Range):
if function_that_decides_to_continue() is CONTINUE:
continue
Another option in an error-handling use-case is directly handling those exceptions with try/except:
def function_that_may_fail(divisor):
return 10 / divisor
for x in [2, 5, 0, 1]:
try:
result = function_that_may_fail(x)
except ZeroDivisionError:
continue
do_stuff_with(result)
Though I admit I might be misinterpreting what you actually want to do, because perhaps the most straightforward "want to be able to continue a for loop if a boolean is true" is just a plain while:
while function_that_decides_to_continue():
# do stuff
You'll have to provide actual examples of the "different for loops" you wanted your "function that continues" will be used in.
While I am in doubt this is a good idea for the flow control of the program, something like this can simulate what you need:
_Range = 6
_RangeEnd = 0
class Continue(Exception):
pass
def function_to_call():
print("x")
if _Continue is True:
raise Continue
for x in ...:
try:
function_to_call()
something_else()
except Continue:
continue
And no, continue can't be outside the loop.
The continue needs to be inside a loop, I think the best solution would be to put a (if boolVar == True: continue) inside the for.
I've created a program that uses pyautogui to locate an image stored in the directory and click on it when it finds it. So when it sees 'Microsoft Edge' it instantly clicks on it. I have this running on a loop and want to stop the loop when it finds the image. This is really important for me—but I want the loop to stop even before it clicks it, so while 'double' is False, as you will see below.
Here it is:
import pyautogui as p
import time
import random
import os
import pygame
from hashlib import sha256
def search(query):
p.hotkey("ctrl","e")
time.sleep(.1)
p.write(query)
p.press("enter")
time.sleep(.67)
def imageFind(image,g,double):
a = 0
b = 0
while(a==0 and b==0):
try:
a,b = p.locateCenterOnScreen(image,grayscale=g)
except TypeError:
pass
if double == True:
p.doubleClick(a,b)
else:
p.click(a,b)
return a,b
#p.hotkey("win","d")
counter = 1
while counter == 1:
image_find = imageFind("Edge.png",False,False)
if image_find == True:
imageFind("Edge.png",False,True)
counter = 0
I've done if image_find == True but it doesn't work as the loop continues.
So how do I code this so that when it finds the image, it stops. How do confirm that what it finds is a True statement?
imageFind does not return a single bool values but instead returns a tuple. your True condition is when both a and b are non zero so change your if image_find == True: to if all(image_find):
all() returns True only if all values are True or non zero
Or try to check if the minimum is nonzero:
if min(image_find):
I want to print whether a number is an anagram or not from the user input. I get an error saying nameError.
And this is my code for checking an input for an anagram.
n = input("Enter a long number")
factor = 2
factor_anagram = False
while factor < 10:
if isAnagram(n, factor):
print(n, "is an anagram with factor", factor)
factor_anagram = True
factor += 1
if not factor_anagram:
print("No")
Do I need to create a class? I tried creating an isAnagram class as well. But my implementation did not solve the issue.
You are trying to use isAnagram(n, factor) as a built in function like print("xyz"). isAnagram() is not a built in function, so you will have to define it at the top of your code. It can look like this:
def isAnagram(n, factor):
if (whatever comparison needs to be made here):
return True
else:
return False
Now when you call the isAnagram function, either True or False will be returned.
isAnagram does not exist in the default Python library - you have to define it yourself. From the way you're attempting to use it, you want to create a function
def is_anagram(n, factor):
# Your code here
# return True or False
You can then do something like if is_anagram(n, factor):.
I am trying to validate input using Python for simple fields.
map_x of type int
map_y of type int
obstacles of type bool
I have tried many of the suggestions here on SO. My code:
class Map(object):
def __init__(self):
# Note: These are defaults.
# map_x and map_y both have a range of 20 <= x <= 100
# obstacles = 'Y' || 'N'
self.map_x = -1
self.map_y = -1
self.obstacles = '-'
def forest_map(self):
self.map_x = self.choice("Map Width")
self.map_y = self.choice("Map Length")
self.obstacles = self.choice("Obstacles (Y/N)")
def choice(self, text):
# Code
I have tried several different solutions at an attempt at staying true to the concept of "efficient" and "re-usable" code.
The reason for the text argument found in method 'choice': I have made prompts that indicate what the user is interacting with (e.g. choice = raw_input(text + "-> ")).
My solutions:
I have tried testing with if statements for the text argument, but that, to me, is too particular to this solution; thus, not re-usable.
I have tried using try / except, but, even still, it seems that my while statement is consuming input and is not returning a value to map_x and map_y.
I have tried (successfully! in a previous section for menu selection, not gathering user preferences) using a dictionary as follows:
# menu is an argument that takes a dictionary.
# dictionary can be found in a list of dictionaries named menu_list.
# choice is a member of class Menus, and menu_list is defined in Menu's __init__.
def choice(self, menu):
acceptable = menu
if menu == self.menu_list[2]:
choice = raw_input("Choice-> ")
while choice not in acceptable:
choice = raw_input("Choice-> ")
Map().generate(choice)
I was only successful in testing for 'obstacles'. I used (while choice not in ['Y', 'y', 'N', 'n']: #Code
As of right now, I am only having issues with testing for integers WHILE keeping true to the aspect of re-usability and efficiency.
Is there a way I can see if the input (choice) contains letters of any kind and, thus, request for more input?
Is there a way I can, simultaneously, ensure that map_x / map_y are within the range 2 <= choice <= 100?
Thanks a bunch,
Akratix
=== EDIT 10/2/14 ===
I have come up with two implementations thanks to the solutions below.
In order to to validate input that is supposed to be an integer as well as within a set range, I use the following code snippet:
def map_choice(self, text):
is_valid = False
while not is_valid:
try:
value = int(raw_input(text + "-> "))
if 2 > value or 100 < value:
print "Invalid input!"
continue
return value
except ValueError:
print "Invalid input!"
In order to to validate input that is supposed to be a particular letter in a "list" of acceptable input, I use the following code snippet:
def obstacle_choice(self, text):
is_valid = False
while not is_valid:
value = raw_input(text + "-> ")
if any(value == x for x in ('Y', 'N', 'y', 'n')):
return value
You're off to a great start, but don't go overboard trying to generalize everything. You have two vastly different fields with different validation, so it makes sense to use two different "choice" functions.
It will be much simpler to use something like the following. You can even customize the fields error messages to tell the user why his input is invalid and be more helpful in general.
def forest_map(self):
self.map_x = self.map_choice("Map Width")
self.map_y = self.map_choice("Map Length")
self.obstacles = self.obstacle_choice("Obstacles (Y/N)")
def map_choice(self, message)
# here we use try except to make sure its an integer
try:
value = int(raw_input(message))
except ValueError:
print "Invalid input!"
return -1
# check range
if 20 > value or 100 < value:
print "Invalid input!"
return -1
return value
def obstacle_choice(self, message):
value = raw_input(message)
# check if its an acceptable answer
if any( value == x for x in ('Y', 'N', 'y', 'n') ):
return value
print "Invalid input!"
return -1
Alternately, if you have a lot of fields, it might be worthwhile to have one choice function that takes a validation function as an argument. Similar to your second choice function, but instead of taking a "menu" dict, we take a validation function.
def forest_map(self):
valid_map = lambda x: 20 <= int(x) <= 100
valid_obstacle = lambda x: any( x == y for y in ('Y', 'N', 'y', 'n') )
# the choice function will guarantee its safe to use int on the result
self.map_x = int(self.choice("Map Width", valid_map))
self.map_y = int(self.choice("Map Length", valid_map))
self.obstacles = self.choice("Obstacles (Y/N)", valid_obstacle)
def choice(self, message, validate):
"""
Prompt a user for input and validate the input
Args:
message (str): Message to display at prompt
validate (callable): callable of one parameter to validate input
Returns:
str: A valid user input
"""
is_valid = False
while not is_valid:
# prompt for input
value = raw_input(message)
# validate input with our validation function
# if validate(value) returns True, it ends the loop
try:
is_valid = validate(value)
# maybe the validation function throws an exception
# its best to catch the specific error class, but I'll use Exception for simplicity
except Exception:
is_valid = False
return True
Finally, as to checking if an input contains any letters. You can use the isalpha method, which checks if every character in a string is a letter. To check if any char in a string is a letter you can use this.
value = raw_input('>')
contains_letters = any( c.isalpha() for c in value )
Give the choice function an additional argument, which I usually call type (despite the collision with a builtin), that is a callable that will transform and validate the argument.
Use this example like IntRange(2, 100)
class IntRange(object):
def __init__(self, min, max):
self.min = min
self.max = max
def __call__(self, s):
i = int(s) # throws
if self.min <= i <= self.max:
return i
raise ValueError('%d is out of range' % i)
More types I've implemented are here: https://github.com/o11c/attoconf/blob/master/attoconf/types.py ; the enum type may be useful for y/n answers (but you might want something that does case normalization as well)
I am somewhat new to Python, and this is a homework question, so I would appreciate no answers, just advice to help me understand. I am writing a game program that plays two different strategies against each other - a greedy strategy and a zoom-in strategy, which I have written as function. I have a game function that needs to pass in my greedy and zoom-in functions, as well as a game board. I need to be able to have either strategy function go first. So far I can only get it to where my greedy strategy goes first.
def game(P1,P2,board):
P1 = 0
P2 = 0
for x in range(len(board)):
if x%2 == 0:
move = greedy(board)
P1 += board[move]
board.remove(board[move])
else:
move = zoomin(board)
P2 += board[move]
board.remove(board[move])
if P1 > P2:
return 1
elif P1 == P2:
return 0.5
else:
return 0
This strategy always assumes that P1 is the greedy function, but I need to be able to play either first. I thought I could pass in the functions, so my call would be
game(greedy,zoomin,board)
but I am not sure how to actually implement it so that it can recognize who is playing first.
Thank you in advance for your help!
EDIT:
Here are my greedy and zoomin functions:
def greedy(board):
if board[0] > board[len(board)-1]:
#returns position of first item
return 0
elif board[len(board)-1] > board[0]:
#returns position of last item
return len(board)-1
else:
#if board[-1] == board[0]
return 0
def zoomin(board):
if len(board)%2 == 0:
evens = 0
odds = 0
for x in range(len(board)):
if x%2 ==0:
evens += board[x]
else:
odds += board[x]
if evens > odds:
return 0
else:
return len(board)-1
else:
#choose the larger value (greedy)
if board[0] < board[len(board)-1]:
return len(board)-1
else:
return 0
This is not a direct answer to your question (since senshin already answered it), but I wanted to point out that you can decrease your code duplication by using arrays instead. For instance, like this:
def game(players, board):
scores = [0] * len(players)
while i in range(len(board))
p = i % len(players)
move = players[p](board)
scores[p] += board[move]
del board[move] # <-- This is also a faster and more fail-safe version of your "board.remove(board[move])"
return scores
You can then call this function as game([greedy, zoomin], board). Also note how it extends to an arbitrary number of players, although that may not actually be useful for you. :)
You will want to rewrite your game function slightly. Notice that your game function accepts P1 and P2, but you don't do anything with them - you immediately assign 0 to both of them.
The correct way to approach this is to have your game function accept two strategies, which can be greedy or zoomin, or whatever else you might come up with later.
def game(strategy1, strategy2, board):
You will also need to replace the explicit calls to greedy and zoomin in the function body (e.g. move = greedy(board)) with calls to the strategies passed into your function instead - something like move = strategy1(board).
Then, in order to have greedy play first and zoomin play second, you could call:
game(greedy, zoomin, board)
Or if you wanted zoomin first and greedy second, you could call:
game(zoomin, greedy, board)
As you can see, the order of play is determined by the order in which you pass the two strategies into your function. Let me know if this needs clarification.