Recursive function that saves a number provided certain conditions - python

I'm trying to create a function in Python that, using recursion, saves a certain number if it is greater than or equal to another previously provided in input (and saved on another variable).
a = 6
def attempts(k):
n = int(input("How many attempts do you want to make? "))
if n>=k:
return n
else:
print("You must make at least {} attempts to play!".format(k))
attempts(k)
b = attempts(a)
The problem is that, if I don't immediately insert the "correct" number, the variable "b" becomes a NoneType. How can I solve this problem?
Sorry for any typos, I'm not a native speaker.

Change your last line of the function to:
return attempts(k)
Currently, results starting from the first recursive call (if it occurs) are thrown away, which results in None being returned by the outermost call.

In the else statement, you are not returning anything, setting b equal to nothing. Add a return statement in the else statement and return whatever you want b to equal to if the else statement comes up.
The way your code works right now, you should add return attempts(k) in your else statement and remove the current last line, attempts(k) This will work the same, except b will have a value.

In the else case you evaluate attempts(k) but don't return it. So it's evaluated as a None. Change
attempts(k)
To
return attempts(k)

Related

I can't put "continue" command in a definition?

Let's say,
def sample():
if a==1:
print(a)
else:
continue
for i in language:
a=i
sample()
I want to use this function in a loop, but the continue command gives me an error because there is no loop. What can I do?
Return a boolean from the function and based on the return value make continue or not because continue must be within a loop
continue keyword in python is only available in for or while loops. Also block defined variables like a are not available on the global scope.
I don't know what you want to achieve but assuming your code, you want to extract a condition into a function, something like this:
def condition(a):
return a == 1
def sample(a):
print(a)
for i in language:
a=i
if condition(a):
sample(a)
else:
continue
There are several best-practice patterns of exactly how to do this, depending on your needs.
0. Factor your code better
Before doing any of the below, stop and ask yourself if you can just do this instead:
def sample(a):
print(a)
for i in language:
if i != 1:
continue
sample(i)
This is so much better:
it's clearer to the reader (everything you need to understand the loop's control flow is entirely local to the loop - it's right there in the loop, we don't have to look anywhere else farther away like a function definition to know when or why or how the loop will do the next thing),
it's cleaner (less boilerplate code than any of the solutions below),
it's more efficient, technically (not that this should matter until you measure a performance problem, but this might appeal to you; going into a function and coming back out of it, plus somehow telling the loop outside the function to continue - that's more work to achieve the same thing), and
it's simpler (objectively: there is less code complected together - the loop behavior is no longer tied to the body of the sample function, for example).
But, if you must:
1. Add boolean return
The simplest change that works with your example is to return a boolean:
def sample(a):
if a==1:
print(a)
else:
return True
return False
for i in language:
if sample(i):
continue
However, don't just mindlessly always use True for continue - for each function, use the one that fits with the function. In fact, in well-factored code, the boolean return value will make sense without even knowing that you are using it in some loop to continue or not.
For example, if you have a function called check_if_valid, then the boolean return value just makes sense without any loops - it tells you if the input is valid - and at the same time, either of these loops is sensible depending on context:
for thing in thing_list:
if check_if_valid(thing):
continue
... # do something to fix the invalid things
for thing in thing_list:
if not check_if_valid(thing):
continue
... # do something only with valid things
2. Reuse existing return
If your function already returns something, or you can rethink your code so that returns make sense, then you can ask yourself: is there a good way to decide to continue based on that return value?
For example, let's say inside your sample function you were actually trying to do something like this:
def sample(a):
record = select_from_database(a)
if record.status == 1:
print(record)
else:
continue
Well then you can rewrite it like this:
def sample(a):
record = select_from_database(a)
if record.status == 1:
print(record)
return record
for i in language:
record = sample(a)
if record.status != 1:
continue
Of course in this simple example, it's cleaner to just not have the sample function, but I am trusting that your sample function is justifiably more complex.
3. Special "continue" return
If no existing return value makes sense, or you don't want to couple the loop to the return value of your function, the next simplest pattern is to create and return a special unique "sentinel" object instance:
_continue = object()
def sample(a):
if a==1:
print(a)
else:
return _continue
for i in language:
result = sample(i):
if result = _continue:
continue
(If this is part of a module's API, which is something that you are saying if you name it like sample instead of like _sample, then I would name the sentinel value continue_ rather than _continue... But I also would not make something like this part of an API unless I absolutely had to.)
(If you're using a type checker and it complains about returning an object instance conflicting with your normal return value, you can make a Continue class and return an instance of that instead of an instance of object(). Then the type hinting for the function return value can be a type union between your normal return type and the Continue type. If you have multiple control flow constructs in your code that you want to smuggle across function call lines like this.)
4. Wrap return value (and "monads")
Sometimes, if the type union thing isn't good enough for some reason, you may want to create a wrapper object, and have it store either your original return value, or indicate control flow. I only mention this option for completeness, without examples, because I think the previous options are better most of the time in Python. But if you take the time to learn about "Option types" and "maybe monads", it's kinda like that.
(Also, notice that in all of my examples, I fixed your backdoor argument passing through a global variable to be an explicit clearly passed argument. This makes the code easier to understand, predict, and verify for correctness - you might not see that yet but keep an eye out for implicit state passing making code harder to follow and keep correct as you grow as a developer, read more code by others, and deal with bugs.)
It is because the scope of the function doesn't know we are in a loop. You have to put the continue keyword inside the loop
continue keyword cannot be used inside a function. It must be inside the loop. There is a similar question here. Maybe you can do something like the following.
language = [1,1,1,2,3]
a = 1
def sample():
if a == 1:
print(a)
return False
else:
return True
for i in language:
if sample():
continue
else:
a = i
OR something like this:
language = [1,1,1,2,3]
a = 1
def gen(base):
for item in base:
if a == 1:
yield a
else:
continue
for i in gen(language):
a = i
print(a)

why one line python loop and traditional loop return different results?

I have array, where I for sure know, there are two objects, which meet conditions, that I want to loop
if I do
def filter_checks_by_lcode_and_admin(admin_uid, lcode, checks):
result = []
for check in checks:
if check.lcode == lcode and check.admin == admin_uid:
result.append(check)
return result
returns correct array with 2 objects
but this code
def filter_checks_by_lcode_and_admin(admin_uid, lcode, checks):
return [check for check in checks if check.admin == admin_uid and check.lcode == lcode]
return 0
what im I doing wrong ?
Until we have a sample input, we can only speculate. In principle both versions of your code should be equivalent, but just to be sure write the conditions in the same order in both:
def filter_checks_by_lcode_and_admin(admin_uid, lcode, checks):
return [check for check in checks if check.lcode == lcode and check.admin == admin_uid]
If that changes the result, then it's because your code has some kind of side effect that makes the result be different between invocations depending on the order of execution. Certainly something to avoid, as you can see, it'll lead to hard to find bugs.
Also you can try executing your code with the same input, but trying the second snippet first and the first snippet later. If this works, then again it'll be a sign that something is changing the state of the inputs between executions, definitely a problem that should be fixed.

How can I get a recursive python function to return a value?

I am new to python and I am just writing a simple recursive function to return the GCD of two integers. If I use a print statement in the gcd function, the function works just fine. But, if I get the function to return the value and try to print the return value outside the function, nothing is printed. This might be a small problem but I have tried numerous things and nothing worked. What am I doing wrong here?
def gcd(m,n):
if m==n:
return m
else:
if m>n:
gcd(m-n,n)
else:
gcd(m,n-m)
m=int(input('Enter first number'))
n=int(input('Enter second number'))
out=gcd(m,n)
print(out)
When you do the recursive call, you want to also return its return value. Otherwise, whenever it calls itself, it doesn't do anything to the value it gets, and just returns None by default.
return gcd(m,n-m)

How can I update different arguments to the same function?

I have a function R(t) defined as:
def R(t) :
if t > 0 :
return "R"
else :
return 0
Now, I want to have several instances of this function working at once. For example, whenever a given condition is met, I would like to generate an R(2) and then, for every iteration of a for loop, I would like to subtract 1 from the argument. My problem comes when the condition is met several times in distinct iterations of the loop, so while there might be an R(2) just appearing, there will be an R(1) turning into an R(0).
I am barely learning how to use python, but I don't think that the code enabling me from accomplishing what I want is very hard. I believe that maybe if I define R(t,j) and use jas an indexing parameter it might be easier to code.
A recursive function that does what you want is:
def R(t):
if t > 0:
print "R"
return R(t-1)
else:
print t

Python – Breaking out of a deeply nested loop with `while`, `try`, `if`, and `except` statements

Here is my code that solves a quadratic equation given user inputs a, b, c. However, I want to check for incorrect user inputs. If a user inputs anything but a float, the user is confronted with print "Not a valid input. Try again.\n" followed by a loop of the function quadratic2(). However, this program is part of a larger program, so I want the user to have the option of typing in "next" to terminate this function and move on. My issue is that I am calling for 3 user inputs, but I want the "next" input to be the first input, a. This works perfectly well until the user types in a random string, causing a ValueError. Once this happens, my code does not want to loop back to check for if the input is next. Please help me! I think something about the way this code is nested is messing me up.
def retest3():
print "Type in another a, b, and c. Or type \"Next\" to move on."
def quadratic1():
print ("This program calculates the zeroes of a quadratic equation."
"\nPlease enter a, b, and c, hitting \"Enter\" after each one: ")
def quadratic2():
while 1 == 1:
a = (raw_input())
if "next" == a.lower():
ontonextthing()
return 1 == 0
else:
try:
a = float(a)
except ValueError:
print "Not a valid input. Try again.\n"
quadratic2()
try:
b = float(raw_input())
except ValueError:
print "Not a valid input. Try again.\n"
quadratic2()
try:
c = float(raw_input())
except ValueError:
print "Not a valid input. Try again.\n"
quadratic2()
if b**2-4*a*c>0:
root1=(-b+math.sqrt(b**2-4*a*c))/(2*a)
root2=(-b-math.sqrt(b**2-4*a*c))/(2*a)
print ("First Root: {0}\nSecond Root: {1}".format(root1,root2))
else:
print ("The discriminant is negative, so your"
" roots will contain \"i\".")
disc1=(b**2-4*a*c)
disc2=-disc1
sqrtdisc2=(math.sqrt(disc2))/(2*a)
b2=(-b)/(2*a)
print ("{0} + {1}i".format(b2, sqrtdisc2))
print ("{0} - {1}i\n".format(b2, sqrtdisc2))
retest3()
quadratic1()
quadratic2()
This works perfectly well until the user types in a random string, causing a ValueError. Once this happens, my code does not want to loop back to check for if the input is next.
Seems like you want the continue statement:
try:
b = float(raw_input())
except ValueError:
print "Not a valid input. Try again.\n"
continue
The continue statement takes you back to the beginning of your while loop (the next iteration). Currently you are calling quadratic2() which makes your function recursive, and not what you want.
Because it's recursive, when you receive your Exception it exits the current function, but because you were using recursion, you simply return back to the previous function you were in the middle of (which is the same function). Therefore the next input you type could be parsed by
b = float(raw_input())
instead of
a = (raw_input())
The "real" solution for your problem is not to use deeply nested constructs in the first place. Deeply nested statements make your code hard to read, hard to test, hard to maintain and hard to reuse. Also, you will tend to duplicate code, which is bad. Especially in Python, deep nesting will cause you to count spaces to get the indentation right, which is really a pain in the neck.
Break your code into functions, and follow the "single responsibility principle" by letting one function do exactly one thing. This has several advantages:
You don't have to keep too many things in your mind. Focus on one small problem, and be done with it.
You can always return early in a function, so you can avoid nesting in many cases.
You can reuse the code in your function.
You don't have duplicate code: If you want to change a particular behavior, change one function instead of several places in one function.
You can test your functions in isolation, making sure that they do the right thing.
In your case, the quadratic2 function does a lot of things:
It runs a "main loop"
It reads user input for commands
It dispatches the command
It reads user input for values
It handles invalid user input
It does computations
It displays the result back to the user
Now I don't say that you need one function for every detail listed above, but it is rather obvious that this function does too much.
Examples on how you could break it up:
Make one function for the main loop and for dispatching commands. Let the commands (such as "next") be handled in separate functions.
Write one function to read in a float from the user, and call this three times instead of repeating the try...except code three times. This has the added benefit that you can enhance this function to run in a loop, so that the user is asked to repeat the input for one value, instead of having to start all over again as your current solution does.
Other tips:
Don't use else after return, raise, break, or continue. It is not necessary, since the next statement will not be reached anyway, and you can save one nesting level.
Don't use confusing expressions like 1==1 or 1==0. This is just a complicated way of writing True and False. In your example, it should read while True and return False instead.

Categories

Resources