I'm beginner python fan.
Note - I know, one "return" is missing.
Purpose of function: sequences with a repeating beginning are given. We don't know how long these "prefixes" are, but we do know there are 7 different ones (the same length). We need to find these prefixes.
However, I am curious how the program works without that word. Why does the function print sets (last line) - shouldn't it still stop at else: search (...), go back to the top, and throw out just None when set is long enough?
I also noticed that if I put print between 'else:' and 'search(...)', the sets are printed in the normal order, and if under 'search(...)'- in the reverse order (ie from where the words are longest).
I would be grateful if someone could explain why it prints at all and in reverse order :)
def search(seq_list, length, position=1):
seq_set = set()
for a in seq_list:
seq_set.add(a[:position])
if len(seq_set) == length:
return seq_set
else:
search(seq_list, length, position + 1)
print(seq_set)
No, it won't stop. A function doesn't return just because a recursive call returns. search finishes, returns its value, then the caller ignores that value and continues on to print(seq_set).
It's not clear that it "works", since you are printing the local value of seq_set, not the one the recursive call returns and you ignore.
Related
I am currently taking a Data Structures & Algorithms course, and while learning about Stacks, the instructor has presented a function called check_parens(), which takes an expression as input and checks to see if the parentheses in the expression are well-balanced.
The function is as follows:
def check_parens(expr):
s = Stack()
for c in expr:
if c == '(':
s.push(c)
elif c == ')':
if s.empty() or s.pop()!='(':
return False
return s.empty()
I understand that this function works properly, but I do not understand why "s.pop() != '('" is included in the inner if condition other than to pop off the current element in the stack should it not already be empty. Otherwise, what is the point in checking if an element in the stack is not equal to '('? With this code, the stack will never contain anything but open parentheses.
With this code, the stack will never contain anything but open parentheses.
With this code, yes. But if you for example also allow {} and [], you'll want a check there. Maybe that's your upcoming homework, and they want to be consistent. Or it's just because in general, you don't just store the same value over and over again. Then you could just count up and down instead of using a stack at all. You use a stack when you want to remember different values. But In order to be sure about their motive, you'd have to ask them.
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.
so first thing I'm new to python and I came across a simple problem but still complicated. Basically I try to loop all of the things from a list, and make them go through a conditional check if there the ones.
This is to check if a sentence is a greeting.
greets = ["Hi","Hello", "Hey"]
#Thinking
def isGreet(mes): #Checks if it's a greeting
words = mes.split()
for greet in greets:
print(greet)
if (words[0]==greet):
return 1;
else:
return 0;
When a user types in something, the code should check if it's a greeting, and if it is, return true, and if it's not return false. Simple, isn't it? But when I type in something, the code only returns true if it's hi which is used, but when i type let's say hello there, it would return false. I added a print function to see if loops works, but it only prints Hi, so I concluded that there must be something wrong with the for loop. Reaally appreciate any help.
The for-loop only loops once, so it's like there was no loop used
yes, because you're returning from the function no matter what at the first iteration. So your test works if the first word tested is the first in the list only. Else it returns 0.
no need for a loop, use in
greets = {"Hi","Hello", "Hey"} # set should be faster, only if a lot of words, though
def isGreet(mes):
return mes.split()[0] in greets
as stated in comments, mes.split()[0] is somehow wasteful because it keeps splitting other words we don't need, so replace by mes.split(maxsplit=1)[0] or mes.split(None,1)[0] for python 2.
I am assuming that you expect the greeting to be the very first word. In that case you can do it in 1 line:
isGreet = True if mes.split(maxsplit=1)[0] in greets else False
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
This question already has answers here:
Why does my recursive function return None?
(4 answers)
Closed 7 months ago.
I don't get it, how can i return a List instead of a None?
class foo():
def recursion(aList):
if isGoal(aList[-1]):
return aList
for item in anotherList:
newList = list(aList)
newList.append(item)
recursion(newList)
someList = [0]
return recursion(someList)
Basically the code is to record all paths (start at 0). Whoever gets 100 first will be returned. isGoal() is to check if last item of the path is 100. And anotherList is a small list of random numbers (from 0 to 100).
return statement
This problem actually took me quite a while to grasp when I first started learning recursion.
One thing to keep in mind when dealing with Python functions/methods is that they always return a value no matter what. So say you forget to declare a return statement in the body of your function/method, Python takes care of it for you then and does return None at the end of it.
What this means is that if you screw up in the body of the function and misplace the return or omit it, instead of an expected return your print type(messed_up_function()) will print NoneType.
Recursion fix
Now with that in mind, when dealing with recursion, first make sure you have a base case besides the inductive case, I.e. to prevent an infinite recursive loop.
Next, make sure you're returning on both cases, so something like this:
def recur(val):
"""
takes a string
returns it back-to-front
"""
assert type(val) == str
# the base case
if len(val) == 1:
return val
# the inductive case
else:
return val[-1] + recur(val[:-1]) # reverses a string char by char
So what this does is it always returns and is 100% infinite recursion proof because it has a valid base case and a decremented length at each inductive step.
Stack Viewer to debug recursive functions
In case we would run recur('big') with the added assert False at the start of the base case, we would have this stack structure:
From it we can see that at each recursive step, we have val, which is the only parameter of this function, getting smaller and smaller until it hits len(val) == 1 and then it reaches the final return, or in this case assert False. So this is just a handy way to debug your recursive functions/methods. In IDLE you can access such a view by calling Debug > Stack Viewer in the shell.
The function is this:
def recursion(aList):
if isGoal(aList[-1]):
return aList
for item in anotherList():
newList = list(aList)
newList.append(item)
recursion(newList) # here you ignore what recursion returns
# when execution reaches this point, nothing is returned
If execution reaches my added comment, after the for loop completes, the function exits and nothing is returned. And when you exit a function without having executed a return statement, None is returned. You must make sure that you return something from the recursive function.
I can't advise you on how to re-write the function since I don't know what it is trying to do. It's very far from obvious to me how it needs to be changed. However, what I can say with complete confidence is that you must return something!