I have used pylint to check my code and I am receiving the following suggestion.
'Either all return statements in a function should return an expression, or none of them should. (inconsistent-return-statements)'. The code block is below. I am passing in a value and need to return which value range it belongs to. If I move the return value outside of the if it will return the incorrect count value. Any suggestions?
def findRangeValue(ranges, number):
count = -1
n = 2
for x in range(len(ranges)-n+1):
count += 1
batch = range[x:x + n]
if batch[0] < number <= batch[1]:
return count
You need confirm the function always have a non-empty (not None) return value in most common situation.
Your code will return None when all if statement in the loop failed, need add a final return value outside loop.
example code:
def findRangeValue(ranges, number):
count = -1
n = 2
for x in range(len(ranges)-n+1):
count += 1
batch = ranges[x:x + n]
if batch[0] < number <= batch[1]:
return count
return -1
print(findRangeValue([1,3,5,7,9], 4))
print(findRangeValue([1,3,5,7,9], 10))
result:
1
-1
Your function is written in a way, that it returns a value only if a condition is met i.e .
if batch[0] < number <= batch[1]:
Assume a situation you are consuming the function something like
range_val = findRangeValue([1,2,3], 3)
If the condition was met the return value will be assigned to range_val. But if the condition was not met, then the function returns nothing and your range_val becomes None.
But your code expects it to be a number and not None. So, now you need to check the return value to avoid errors - an extra line of code.
Assume you are calling this function from various parts of your code, every where you need to bring in this check - more and more code.
To avoid this, a standard to follow is that, a function always returns what was promised. If it was not able to do so, raise an Exception so that, the caller is notified without an additional check.
In your particular scenario, you can use a break statement and always return a count outside (beware, if break was not met, the value could be not what you expect) Or use an additional flag variable with break, and raise an error if the flag variable was not set.
Related
Why does the following executes such that the print statement is called as often as it recursed but the count variable, count, when x == 1 is never reached.
def count_bits(n, count = 0):
x = n % 2
if n == 1:
return count + 1
if n < 1:
return count
if x == 1:
count += 1 # when x == 1
count_bits(int(n/2), count)
print("counter")
return count
why is it necessary to recurse with the return statement? Because if the recursive call is above the return statement the code
returns the wrong output but with the recursive call called with
return keyword, everything works well. Typically, the print statement
prints 'counter' as often as it recursed showing that the recursive call
works.
On the other hand, if "return" follows after the recursive call, it returns the count from the base condition, correctly.
def count_bits(n, count = 0):
x = n % 2
if n == 1:
return count + 1
if n < 1:
return count
if x == 1:
count += 1
return count_bits(int(n/2), count)
You have to return recursion result, as reccurent function meaning is to count current step you have to get result of previous step
F_k = F_k-1 * a + b # simple example
Means that you have to get result of F_k-1 from F_k and count current result using it.
I advised you to use snoop package to debug your code more efficient , by this package you can track the executing step by step.
to install it run:
Pip install snoop
Import snoop
add snoop decorator to count_bits()
for about the package see this link
https://pypi.org/project/snoop/
the difference in the output between the two methods is because of the way in which python handles fundamental data types. Fundamental data types such as float, ints, strings etc are passed by value, whereas complex data types such as dict, list, tuple etc are passed by reference. changes made to fundamental data types within a function will therefore only be changed within the local scope of the function, however changes made to a complex data type will change the original object. See below for an example:
x = 5
def test_sum(i : int):
print(i)
i += 5
print(i)
# the integer value in the global scope is not changed, changes in test_sum() are only applied within the function scope
test_sum(x)
print(x)
y = [1,2,3,4]
def test_append(l : list):
print(l)
l.append(10)
print(l)
# the list in the global scope has '10' appended after being passed to test_append by reference
test_append(y)
print(y)
This happens because it's far cheaper computationally to pass a reference to a large object in memory than to copy it into the local scope of the function. For more information on the difference, there are thousands of resources available by searching "what is the difference between by reference and by value in programming".
As for your code, it seems to me the only difference is you should alter your first snippet as follows:
def count_bits(n, count = 0):
x = n % 2
if n == 1:
return count + 1
if n < 1:
return count
if x == 1:
count += 1 # when x == 1
# assign the returned count to the count variable in this function scope
count = count_bits(int(n/2), count)
print("counter")
return count
The second code snippet you wrote is almost identical, it just doesn't assign the new value to the 'count' variable. Does this answer your question?
I found a basic code in python to find the numbers of paths you can take in a (m,n) grid if you can only go either down or right.
def gridtraveller(m,n):
if m == 0 or n == 0:
return 0
elif m == 1 or n == 1:
return 1
return gridtraveller(m-1,n) + gridtraveller(m,n-1)
But I dont understand why is this working for two thing:
What does def something (m,n) do ?
And why does here we return the definition ? ( I do understand why we return
m-1 and n-1 , but I don't understant the concepte of a def returning a def)
Thanks to you and sorry english is not my first language.
In Python the def keyword is simply used to define a function, in this case it's the function gridtraveller(m,n). What you're seeing with that last return statement is actually a function returning the value of another function. In this case it's returning the value of another call to gridtraveller, but with different parameter values; this is called recursion. An important part of recursion is having appropriate base cases, or return values that won't end in another recursive call(i.e. the return 0 or return 1 you see).
It can be easier to understand by simply stepping through a few iterations of the recursive calls. If your first function call starts with m = 2 and n = 1, the first call will end with return gridtraveller(1,1) + gridtraveller(2,0). The first call in that statement will then return 1 since either m or n are 1 and the second returns 0 since n = 0 here giving a total result of 1. If larger values of m and n are used it will obviously result in a higher number since more calls to gridtraver(m,n) will happen.
I have been trying to write a python function which will receive two arguments: x which is the number of times to repeat and y which is the number or string to be repeated.
So far this is what I have been able to come up with, but I can't seem to be able to determine how to do it recursively.
def recurse(x, y):
final = []
if x == 0:
return ("")
else:
x = x - 1
final.append(recurse(x,y))
return final
If recurse(3,"Cat") is called, the output is meant to look like this:
print recurse(3, 'cat')
['cat','cat','cat']
How would I go about doing this?
True functional recursion should have no assignments (i.e. state).
This can be achieved using what's called an accumulator, i.e. an array that is built up successively and passed to each recursive step, until the base case occurs, causing the accumulator's final form to be returned directely, and indirectly all the way back to the initial calling instance.
>>> def recurse(Iters, text, Accumulator=[]):
... if Iters == 0: return Accumulator # base case
... return recurse(Iters-1, text, Accumulator + [text]) # recursive step
...
>>> recurse(3, 'helle')
['helle', 'helle', 'helle']
Note that there is no change of state at any point; all "updates" occur at the point of calling the next recursive step with updated arguments.
def recurse(x, y):
final = []
if times == 0:
You can't just reference "times" as if it's some kind of magic floaty variable available anywhere and everywhere. The first time in here, times will have no value. And the next time through, you're hoping you can just pick the value of times out of thin air and it will magically be what it was somewhere else, during some previous run.
The only variables you can work with are the ones completely inside your function - or ones which are passed in from outside, and returned out at the end.
def recurse(times, word):
if times == 1:
return [word]
else:
return [word] + recurse(times-1, word)
print(recurse(3, 'cat'))
Try it online at repl.it
It takes a number of times as an input, it returns [word] plus ( It takes a number of times - 1 as an input, it returns [word] plus ( It takes a number of times - 1 as an input, it returns [word] ).
Note there's no accumulator list like final = [] because each time through the function it will be empty again. The accumulation happens implicitly in the way the programming language calls functions and returns values. Python will hold [word] in memory itself while it calculates the next recurse() output.
I'm having troubles with a recursive function in Python. The objective is for the function to calculate the sum of the digits of a number recursively.
This is what I have so far -- I realise that this version isn't as succinct as it could be, but right now I'm just trying to understand why it isn't working as is:
total = 0 #global variable declaration
def digit_sum(n):
global total #to be able to update the same variable at every level of recursion
total += n % 10 #adding the last digit to the total
n //= 10 #removing the last digit of the number
if n < 10:
total += n
return total
else:
digit_sum(n)
print 'The return value of the function is: ', digit_sum(12345)
print 'The final value stored in total is: ', total
I obtain the following output:
The return value of the function is: None
The final value stored in total is: 15
My function is somewhat working, since the final value stored in the global variable total is correct, but printing the function output returns None instead of 15.
Could you please help me understand why?
Thank you.
Interesting problem, and an interesting solution! Let me debug with a more simple number - 421.
On first call, total is assigned the value 1 and n becomes 42. The else branch gets executed.
On second call, total gets value of 3 and n becomes 4. The if branch is executed and the value total = 7 is returned.
So, why are we seeing the None? Let's inspect the call-stack:
> digit_sum(n = 421)
> > digit_sum(n = 42) # call to digit_sum from inside digit_sum
> -< 7 # value returned by inner/second call
> None
As you can notice, the value being returned by the second call is received by the first call, but the first call doesn't return the value being returned by the second call, so that's why you are seeing None.
But why does't first call return the value being returned by the second call?
Because of this line:
else:
digit_sum(n)
You are calling the function a second time, but you are not returning its return value.
Hope it helps! :)
The problem is that you didn't add a return statement in your else clause.
Adding 'return digit_sum(n)' should solve your problem:
if n < 10:
total += n
return total
else:
return digit_sum(n)
Example
When you have a recursive function (I'll take n! as example), calls are made until you reach a 'base case' (2 in n! and for you if n<10).
Let's take a look at factorial:
def fact(n):
if(n<=2):
return n
else:
return n*fact(n-1)
Without the return statement in else clause, if you ask for fact(4), this will also return none.
Here are the 'calls' with the return statement:
return (4*fact(3))
return (4*(3*fact(2)))
return (4*(3*(2)))
Which gives 24.
Here are those without:
(4*fact(3))
(4*(3*fact(2)))
(4*(3*(2)))
So the calculus is made, but nothing is returned.
I hope this will help you to understand.
NB: Here is a factorial implementation where recursivity is explained.
my solution is
def f(n):
if n/10 == 0:
return n
return n%10 + f(n/10)
output:
f(12345) = 15
My task is to create a recursive function in Python that takes a list and a value of 0 as its inputs and then adds up all of the odd numbers on the list and returns that value. Below is the code that I have and it keeps returning that the list index is out of range. No matter what I do I can not get it to work.
def addodds2(x,y):
total=0
a=x[y]
while y<len(x):
if a%2!=0:
total+=a
return(addodds2(x,y+1))
else:
return(addodds2(x,y+1))
return(total)
print(addodds2([3,2,4,7,2,4,1,3,2],0))
Since you are trying to solve this recursively, I don't think you want that while loop.
When you are trying to solve a problem recursively, you need two parts: you need a part that does some of the work, and you need a part that handles reaching the end of the work. This is the "basis case".
Often when solving problems like this, if you have a zero-length list you hit the basis case immediately. What should be the result for a zero-length list? I'd say 0.
So, here's the basic outline of a function to add together all the numbers in a list:
Check the length, and if you are already at the end or after the end, return 0. Otherwise, return the current item added to a recursive call (with the index value incremented).
Get that working, and then modify it so it only adds the odd values.
P.S. This seems like homework, so I didn't want to just give you the code. It's easier to remember this stuff if you actually figure it out yourself. Good luck!
Your code should be (the comments explain my corrections):
def addodds2(x,y):
total=0
if y<len(x): #you don't need a while there
a=x[y] #you have to do this operation if y<len(x), otherwise you would get the index error you are getting
if a%2!=0:
total+=a
return total+addodds2(x,y+1) #you have to sum the current total to the result returned by the addodds2() function (otherwise you would got 0 as the final result)
return total
print(addodds2([3,2,4,7,2,4,1,3,2],0))
while y<len(x)
So the last y which is smaller than len(x) is y = len(x) - 1, so it’s the very last item of the list.
addodds2(x,y+1)
Then you try to access the element after that item, which does not exist, so you get the IndexError.
This code can be very short and elegant:
def add_odds(lst, i=0):
try:
return (lst[i] if lst[i] % 2 == 0 else 0) + add_odds(lst, i+1)
except IndexError:
return 0
Note that, in a truly functional style, you wouldn't keep track of an index either. In Python, it would be rather inefficient, though, but recursion isn't recommended in Python anyway.
def add_odds2(lst):
try:
return (lst[-1] if lst[-1] % 2 == 0 else 0) + add_odds2(lst[:-1])
except IndexError:
return 0
To make it work with any kind of sequence, you can do the following:
def add_odds3(it):
it = iter(it)
try:
value = next(it)
return (value if value % 2 == 0 else 0) + add_odds3(it)
except StopIteration:
return 0
It's much more efficient, though there's not much sense in using an iterator recursively...
I realize that little of this is relevant for your (educational) purposes, but I just wanted to show (all of) you some nice Python. :)