Yesterday I posted a question where I was searching for a way to do an infinite for loop, without using while at all (because my teacher wants so, and also, we can't use any commands we haven't seen in class). It was difficult as apparently there wasn't a very viable option that didn't use while, or other functions like itertools or .append, etc.
You can see that question here
Also, thanks a lot for the feedback you guys brought me! :)
But I managed to talk with my teacher and we got permission to use itertools or just a range big enough (instead of actually infinite).
I solved a few exercises already, but now I have the following instructions:
(Think about grades)
• Ask the user a number (through inputs), and keep asking until the user tells to stop.
• Then, calculate the average from all the numbers entered.
(It's actually a little more complex, but I shortened it and I believe I can deal with the rest)
As I said, I must use a for loop, and I can't use whiles at all.
If I could use while, I'd do something like this:
def grades():
totalg = 0
countg = 0
keepAdding = "y"
while(keepAdding == "y"):
qualif = int(input("Insert grades obtained, in scale from 0 to 100 "))
totalg = totalg + qualif
countg = countg + 1
keepAdding = str(input("Do you wish to keep adding data? (y/n) "))
print("The average of your grades is", totalg/countg)
How can I do something like that, but with for loops? I have no idea on how to store the data for later calculation.
Also, I'm interested into knowing a more "proper" way to be able to end the loop, but I can't use a break neither.
Thanks in advance! Any advice is appreciated and welcome! :)
One way to do this is, without outside modules, is to use two-arg iter; when passed two arguments, the first is a no-argument function to call over and over, and the second is a sentinel value than indicates you should stop.
So for example, you could make an infinite loop with something as simple as:
for _ in iter(bool, True):
Since the bool constructor returns False, a sentinel value of True will never occur, so that's an infinite loop.
Similarly, to make a loop that prompts until the user responds with a given sentinel string, like 'q' for quit (or just the empty string), you could do:
for inp in iter(lambda: input("Insert grades obtained, in scale from 0 to 100 (type 'q' to quit)"), 'q'):
val = int(inp)
... rest of loop ...
Obviously, this is a little obscure (two-arg iter is rarely seen), so usually you'd use while True: with the loop containing a test-and-break or test-and-return (the latter doesn't violate the letter of the teacher's requirements). Similarly, exception handling can be used to exit the loop, though it's ugly:
try:
for ...:
if test_for_end:
raise StopIteration
except StopIteration:
pass
# You're outside the loop
Note: Literally everything I've mentioned is terrible style, aside from an actual while True: loop with a test-and-break/return case. But you've got one hand tied behind your back, so I'm suggesting some terrible mutant hands to substitute.
Even though 'no-break' rule and a request for a "proper" way to end a loop are somewhat contradictory, I'd say that is possible, even without return :
grades = [0]
for j in grades:
t = int(raw_input('grade:'))
ans = raw_input('more? [y/n]:').lower()
if(ans == 'y'):
grades.append(t)
else:
grades[0] = t
print(sum(grades)*1.0/len(grades))
here we just iterate over ever-growing list of values, and when we need to stop - we simply stop adding values to it, and the loop ends.
HOWEVER
This is NOT a proper way of handling that issue, read ShadowRanger for more details - this is bad coding style and should not be used.
Maybe saving all the data obtained in an array?
I think arrays on python work as Linked Lists, so you won't have any overflow problems, at least that would be a starting point
Related
I have a relatively large main() function where I need to check a variable several times at different places in the function and then decide if I should continue the loop accordingly, like so:
def main():
while True:
...
if foo.check():
reset()
continue
...
Where foo is working as a time keeper of sorts, therefore I need to check it at certain intervals. These 3 lines appear about 3 to 5 times within the function.
I hate how dirty this is, so is there a cleaner way to do this?
You haven't specified enough information. I have two questions:
Is the call foo.check() idempotent meaning it always returns the same value and has no side-effects?
Is there a path through the code where you can reach the nth call to foo.check() in the same block governed by the continue statement without first calling the n-1th occurrence?
If, for example, the answer to the answer is yes and the second question were no, then you could remove all but the first occurrence of the call to foo.check() because the return value is clearly False or else you would never reach the second occurence.
If the answer to the first question is yes and the second is yes, then if the call to foo_check() is expensive, I might consider up front setting:
check_result = foo.check()
and then replacing every call to foo_check() with check_result. But ultimately you still need to do all the checks. But in all cases you can create a function check_and_reset:
def check_and_reset():
if foo_check():
reset()
return True
return False
Then your code becomes:
if check_and_reset(): continue
I have two suggestions:
Suggestion 1:
Create another function and call wherever you want.
Suggestion 2:
Make it as a one-liner
if foo.check():reset();continue
If it is just a complex way to control some timing while running a set of tasks, I'd suggest to introduce a loop over the tasks. You can even easily pass partial results around:
def task_a():
...
def task_c(some_input):
...
tasks = [lambda x: task_a(), task_c]
last_stage_output = None
while True:
reset()
for task in tasks:
if not foo.check():
break
last_stage_output = task(last_stage_output)
This way, you make it clear that it is just a series of tasks to be done, it's simple to add, remove of reshuffle them, and the timing logic is concentrated in a single point.
I'm fairly experienced with Python, but as I was helping out a friend with a script, I noticed he had solved a common problem in a different way than I was familiar with. He is making sure that the user input is in a valid format (a float); I am used to seeing something like this, which is also what all answers I could find say:
def get_input()
while True:
try:
val = float(input("input pls"))
return val
except:
print("not valid, try again)
He had however solved it using recursion, like this:
def get_input():
try:
val = float(input("input pls"))
return val
except:
print("not valid, try again")
return get_input()
Is there any downside to this?
Some issues or data about this:
There is a recursion limit (very hight, but may surpass)
Each time the get_input method is called recursively its creating a new stack for the scope, even more, it will chain the try...except blocks, this is awful for memory usage and performance.
The recursive method is usually more difficult to debug.
But since it looks like a toy example maybe this just doesnt matter.
I personally would not do that in Python although to me it does look easy to read. The problem with python is that it does not have tail-call optimization where the approach here would be optimised by the compiler as the last thing you are doing is returning the value.
To make this work, you could use a generator based approach so that the number of times a user will get this wrong is independent to whether or not the program can handle it. (This does not look as elegant as the solution you have given but does handle the infinite recursion)
def get_input_from_keyboard():
# I have used raw_input instead of input as I am using python 2.7
return float(raw_input("input pls"))
def try_again():
print("not valid, try again")
for x in get_input():
yield x
def get_input():
try:
yield get_input_from_keyboard()
except ValueError:
for x in try_again():
yield x
list[get_input()][0]
That said, the recursive approach you have provided could be adapted by catching RuntimeError exception but that is very risky as the reason could be that there really is something which has gone wrong apart from a stack overflow.
I am an amateur Python coder learning in school. We recently went over functions and did some work at home. I am confused on the point/meaning of the return statement. Our goal was to simply turn a letter into its ASCII counter part using ord(). My code works as intended however what is the use of the return statement, and how can it be used in this situation to take this function further?
Letter = input("What is your letter? ")
def ordfunction ( x ):
x=ord(x)
print(x)
return[x]
ordfunction(Letter) x
Whenever we write a function it perform some task, on basis of execution it provide some result. Now we have lot of options to use this result.
One we can print/display that result on console. for which we use print to show o/p. Here is use:-
Letter = input("What is your letter? ")
def ordfunction ( x ):
x=ord(x)
print(x)
ordfunction(Letter)
So it will display output on console apart from this it dosn't perform any things. We can use this output to store in a file or send on any device.
Further other way is to use return to provide result of function. Here we can hold this value to use further in any kind of calculation like:-
Letter = input("What is your letter? ")
def ordfunction ( x ):
x=ord(x)
return x
a = ordfunction(Letter)
print (a+100)
So return with provide use result of execution to use it further throughout program.
Further you can refer:-
Why would you use the return statement in Python?
There are basically two things that a method/function can do: change some kind of state or give the caller some kind of information.
For example, if you write something to the console, you've changed something about the system state. This is sometimes called a side effect.
The second thing a method can do is give its caller some kind of information. return is a way to pass data back to the caller - it's the "result" of the method. (In many programming languages, you can also use it to exit a method immediately, but that's a different topic).
Think about a common function: 2 + 3. Most people aren't used to thinking of + as a function, but it is. (If it helps, you can think of this as plus(2, 3)). In this case, the plus function "returns" five - that's the result of the operation, the information you were looking for when you "called" it to begin with.
Hopefully, this clarifies things a little bit - if not please feel free to comment and I can edit.
Quoting definition of a math function:
In mathematics, a function is a relation between a set of inputs and a
set of permissible outputs with the property that each input is
related to exactly one output.
In short, the return is the output. Think about a math function f(x) = x + 100.
x is the input
x + 100 is the implementation of the function
The return is the output of the function, which is the result of x + 100
Equivalent python function:
def f_of_x(x):
result = x + 100
return result
Return is your answer to one statement; example: is it raining? Yes, it's raining
Your answer is returned to your question.
Simple
I also had trouble understanding the difference between return and print. After you return a function you should:
print(ordfunction(Letter))
To see your function. Print is just made for humans to see what is going on. We usually don't need the print function.
This question already has answers here:
How to properly ignore exceptions
(12 answers)
Closed 9 years ago.
I have try-except block in python, and I want to do nothing when exception occurs. My code is as follows:
for i in range(len(grid)):
for j in range(len(grid[i])):
try:
count = count > int(grid[i][j]) ? count : int(grid[i][j])
except:
//Do nothing here
How do I do nothing when exception is caught.
Thanks.
pass is the keyword you are looking for.
Let us write the code properly.
We want to iterate over each cell of the grid. So do that. Don't create lists of numbers (range) that you iterate over and then use to index back in. Python's for-loops work directly with the container. It is convenient and easy to understand and good. Don't fight that.
There is no ?: construct in Python. There is a x if y else z construct, but that is not appropriate here. You are clearly trying to set count to the maximum of its current value and the cell value. There is a built-in function for that.
You really want the maximum of all of those cells. So ask for that directly; don't assume that you have to implement the high-water-mark algorithm yourself. You don't. (This also protects you from having to pick an initial value for count, which might be wrong.) We don't need to iterate with an explicit loop for this. We can specify the list of values to pass to max with a generator expression.
You want to "ignore" values that can't be converted to integers. Notwithstanding that there probably is something wrong with your other code if the existence of such values could possibly occur in the first place: we can simply make a test, and filter out the values that fail the test.
Thus:
def is_integral(value):
try:
int(value)
return True
except:
return False
# Now, get the maximum of all the integral values:
count = max(
int(cell) for row in grid for cell in row
if is_integral(cell)
)
You can use pass, but also ... is synonymous in Python 3.x, which can be nice for writing psuedocode.
I see a lot of people use pass where they truly need to do nothing, while using ... where they are using it as a placeholder.
class SomeInterface:
def do_something(self):
pass
class SomeImplementation(SomeInterface):
def do_something(self)
...
This makes it easy to search for ... and find areas where you have unimplemented code, without the false positives from pass.
Note that passing on an exception is generally a bad practice, as you will virtually always want to act on exceptions. You should definitely, at the very least, specify the exact exception(s) you want to catch, as otherwise you will catch all exceptions, potentially causing bugs you can't detect if a different exception rears it's head.
for i in range(len(grid)):
for j in range(len(grid[i])):
try:
count = count > int(grid[i][j]) ? count : int(grid[i][j])
except:
pass
result = x if a > b else y
Is the ternary operator
The do nothing statement is
pass
Okay, I know you can have a program keep running while a certain condition is true using the while statement. However, is it incorrect or bad practice to just recall the function in the else condition like below?
def ask():
me = input("What is your name? ")
if me == "Tom":
print("Hi, Tom!")
else:
print ("Who are you?")
ask()
It just seems like an easier, shorthand version of the 'while statement' but I haven't really seen a program executed like this in the Python tutorials.
To be totally honest they both "work" it just depends on your user case. Granted you are more likely to hit recursion depth compared to something going wrong with while they both achieve similar results. Really its more simple and in my opinion slightly more pythonic (in this specific case) to use a while loop. (why make it more complicated?)
I wouldn't consider it bad practice unless you expect hundreds to thousands of recursive calls, or if memory management is important for your particular application.
As stated in other answers, Python doesn't support tail recursion elimination, which means that a recursive call to the same function doesn't have to add a new stack frame to the stack. This avoids wasting unnecessary memory.
For an interesting read about why Guido, the creator of Python, considers tail recursion elimination to be unpythonic, see: http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html
Shorthand, you say? Compared to:
def ask():
while input("What is your name? ") != "Tom":
print ("Who are you?")
print("Hi, Tom!")
I suggest to use a while statement, because you will feel difficulties when the ask function become to have its upper limit to try to input and return the result value.
To add these functionality, I modify this function such as:
def ask(count):
if count < 0:
return False
me = input("What is your name? ")
if me == "Tom":
print("Hi, Tom!")
return True
else:
print ("Who are you?")
return ask(count - 1)
Is that implementation so complicated and confusing?
If the ask function is implemented using 'while' statement, the modification is more simple.
Just change 'while' to 'for' to set the loop with an upper limit and insert 'return' statement.