Recursive function without return - Python 2.7 - python-2.7

Can this be called a recursive function ? It does reduce in one way but not in a (amount - 1) type of way...
EDIT:
Also how is it possible to write a recursive function without using return?
def wow(amount):
if amount <= 0:
print "Don't be so negative!"
elif amount == 1:
return "Wow!"
else:
return amount * "Wow! \n"
amount = int(raw_input("How many 'Wow!' do you wanna see : "))
print wow(amount)

No, this is not a recursive function. A recursive function has to call itself. This page explains and shows examples of recursive functions.
This would be a recursive function.
def wow(amount):
if amount <= 0:
return
else:
print("Wow! \n")
return wow(amount - 1)
And a full-fledged solution that turns your code into a recursive function would be.
def wow(amount):
if amount <= 0:
return "Don't be so negative!"
elif amount == 1:
return "Wow!"
else:
return inner_wow("", amount)
def inner_wow(wow_str, amount):
if amount == 0:
return
else:
wow_str += "Wow! \n"
return wow(wow_str, amount - 1)
In response to your second question. All functions have to return something. Even if you don't tell them to return something they still returns None.

Related

(In Python 3.8) filling in lists to mantain them similar in length and average?

I need to allocate some values in 3 individual lists.
The values are generated on the fly but all included in the 0-6 range.
The point is that these values should be put in the three lists so that the average of each list does not differ so much from the others. The lists also need to be similar in length.
So the goal would be to progressively fill these lists to maintain, as much as possible, a uniform average value and size for all of them.
As I didn't found any built-in function to do this, I have implemented a code which keeps track of lists length and tries to keep them as close as possible in their average value. You can play with it and improve it to better fit your case.
class Data:
def __init__(self):
"""Init the three lists."""
self.a = []
self.b = []
self.c = []
#staticmethod
def get_average(data: list):
"""Get average value of a list."""
try:
return sum(data) / len(data)
except ZeroDivisionError:
return 0
def get_shortest(self):
"""Return list with the shortest length."""
shortest_length = min(len(self.a), len(self.b), len(self.c))
if len(self.a) == shortest_length:
return self.a
elif len(self.b) == shortest_length:
return self.b
else:
return self.c
def get_smallest(self):
"""Return list with the smallest average value."""
smallest_average = min(self.get_average(self.a), self.get_average(self.b), self.get_average(self.c))
if self.get_average(self.a) == smallest_average:
return self.a
elif self.get_average(self.b) == smallest_average:
return self.b
else:
return self.c
def get_highest(self):
"""Return list with the highest average value."""
highest_average = max(self.get_average(self.a), self.get_average(self.b), self.get_average(self.c))
if self.get_average(self.a) == highest_average:
return self.a
elif self.get_average(self.b) == highest_average:
return self.b
else:
return self.c
def add_number(self, num):
"""Add number to one of the lists."""
shortest = self.get_shortest()
smallest = self.get_smallest()
highest = self.get_highest()
# Lists must not differ by more than two elements
if len(smallest) - len(shortest) >= 2 or len(highest) - len(shortest) >= 2:
shortest.append(num)
else:
# Test if the number uppers the smallest average
initial_avg = self.get_average(smallest)
smallest.append(number)
final_avg = self.get_average(smallest)
if final_avg > initial_avg:
return
else:
smallest.pop()
# Test if the number lowers the highest average
initial_avg = self.get_average(highest)
highest.append(number)
final_avg = self.get_average(highest)
if final_avg < initial_avg:
return
else:
highest.pop()
# Last resort
shortest.append(num)
d = Data()
value = input("Add number: ")
while value != 'e':
try:
number = int(value)
except ValueError:
break
d.add_number(number)
print(f"List a: {d.a}, avg. {d.get_average(d.a)}")
print(f"List b: {d.b}, avg. {d.get_average(d.b)}")
print(f"List c: {d.c}, avg. {d.get_average(d.c)}")
value = input("Add number:")

Python embedded function returns None

I have a very simple function which summarize the list elements without using sum function or looping technique. Here it is:
def find_sum(mylist):
def get_value(sublist, counter):
counter += sublist.pop()
if sublist:
get_value(sublist, counter)
else:
print counter # It will print correct result
return counter
my_sum = get_value(mylist, 0) # But my_sum is None
return my_sum
Why the emdedded function returns None?

(Python) How to stop calculation after a ZeroDivisionError

Is there a way to stop everything after an exception?
For example, I'm creating a reverse polish notation calculator (to learn postfix) and I want to make sure "Cannot divide by zero" is printed out if there is a "0" in my string.
I got it to do what I wanted using try/except.
I tried putting in a "break" after my print statement in the exception but that obviously does not help because my final "pop" is outside the loop. And that causes a bunch of traceback error as obviously the "divide by zero" operation was not performed and the list becomes messed up.
Any ideas?
def RPN(ll):
mys = Stack()
for x in ll:
if x == '+':
sum_of_two = mys.new_pop() + mys.new_pop()
mys.push(sum_of_two)
"""mys.print_stack()""" #test addition
elif x == "*":
product = mys.new_pop() * mys.new_pop()
mys.push(product)
"""mys.print_stack()""" #test multiplication
elif x == "-":
subtrahend = mys.new_pop()
minuend = mys.new_pop()
subtrahend
minuend
difference = minuend - subtrahend
mys.push(difference)
"""mys.print_stack()""" #test subtraction
elif x == "/":
divisor = mys.new_pop()
dividend = mys.new_pop()
divisor
dividend
try:
quotient = dividend/divisor
mys.push (quotient)
except ZeroDivisionError:
print "Cannot divide by zero"
"""mys.print_stack()""" #test division
else:
mys.push(int(x))
return mys.new_pop()
example = [3,4,"-",5,"+",6,"*",0,"/"] #test reverse polish calc
print RPN(example)
You can return a value from anywhere in a function, not just at the end
try:
quotient = dividend/divisor
mys.push(quotient)
except ZeroDivisionError:
print 'Something to console'
return None
Of course, whatever called this function is going to have to accept None as a valid return value.
Alternatively, if this is a function way down in the control chain, and you want to just bubble all the way up to the top function, just re-raise the error, or raise a different error and catch it at the very top function.
class MyError(Exception):
pass
def func():
try:
func2()
except MyError as e:
print e.message
def func2():
func3():
def func3():
RPN([...])
def RPN(ll):
...
try:
...
except ZeroDivisionError:
raise MyError('Zero Division')

(Super beginner) Can someone explain what's going wrong with my lists?

Ok, so, this is the longest code I've ever written, so I apologize if it's a bit messy. First computer science assignment ever.
def main():
#generate random value
import random
rand = random.randint(1, 99)
#instructions
print("""The purpose of this exercise is to enter a number of coin values
that add up to a displayed target value. Enter coins as 1=penny, 5-nickel,
10-dime, 25-quarter. Hit return after the last entered coin value.""")
#defining function for 'first coin'
def firstCoin ():
coins = []
global coins
coin = int(input("Enter first coin: "))
if coin > rand:
print("Sorry, total value exceeds", rand, "cents.")
again = input("Try again (y/n): ")
if again == "y" or "Y":
main()
else:
sys.exit() #ends program
elif coin in possible:
coins.append(coin)
nextCoinplease()
#defining function for 'next coin'
def nextCoinplease ():
while True:
nextcoin = (input("Enter next coin: "))
if nextcoin in possible:
coins.append(nextcoin)
elif nextcoin == "":
break
else: print("Invalid entry.")
#making lists
possible = [1, 5, 10, 25]
print("Enter coins that add up to", rand, "cents, one per line.") #program start
firstCoin ()
sumcoin = sum(coins)
print(sumcoin)
if sumcoin == rand:
print("Correct!")
else:
print("Invalid entry.")
firstCoin()
main()
So, this is my issue. For some reason, user input in the function nextCoinplease does not get added to the list "coins", only the first input from the function firstCoin does. This means that sum(coins) is literally only the first input. I cannot for the life of me figure out why, so any input would be greatly appreciated, thanks!
You have two input statements, one to get coin and one to get nextcoin. They are different. What's the difference?
(I'm deliberately not giving the answer outright because from what you've written so far, I am sure you can figure this one out given this hint.)
The return type of input is a string, so nextcoin in possible always fails since possible only contains integers. Try using int() to parse the input as an integer.
Your code never gets to check if the rand is equal to sumCoin, so it never stopped. I've fixed the problem, this code works now.
Demo on repl.it
What did I do?
I moved your if statement that checked if rand == sumCoin at the beginning of the while loop in nextCoinPlease(), so that it will check the sumCoin value before entering each next coin value and will stop once it equals rand.
Code:
import random
import sys
def main():
rand = random.randint(1, 99)
print('''The purpose of this exercise is to enter a number of coin values \
that add up to a displayed target value. Enter coins as 1=penny, \
5=nickel, 10-dime, 25-quarter. Hit return after the last entered \
coin value.''')
coins = []
def firstCoin():
coin = int(input("Enter first coin: "))
if coin > rand:
print('Sorry, total value exceeds ', rand, ' cents.')
again = input('Try again? (y/n): ')
if again == 'y' or 'Y':
main()
else:
sys.exit()
elif coin in possible:
coins.append(coin)
nextCoinPlease()
def nextCoinPlease():
while True:
sumCoin = sum(coins)
print('Total Value: ' + str(sumCoin))
print ''
if sumCoin == rand:
print('Correct! You Win!')
sys.exit()
elif sumCoin > rand:
print('You exceeded the total value! You lose! Try again!')
sys.exit()
nextCoin = (input('Enter next coin: '))
if nextCoin in possible:
coins.append(nextCoin)
elif nextCoin == "":
break
else:
print('Invalid entry.')
possible = [1, 5, 10, 25]
print('Enter coins that add up to', rand, 'cents, one per line.')
firstCoin()
main()

How to pass a method to timeit in python?

So I am working on comparing the iterative and recursive ways of finding fibonacci numbers. I wanted to pass them both into timeit, but am having trouble formatting my calls to timeit. Good someone give me a little guidance please? Thanks!
import timeit
def it_fib(n):
total = 0
while n > 0:
total += n
n -= 1
return total
def rec_fib(n):
if n == 0:
return 0
else:
return n + rec_fib(n-1)
#print (it_fib(10))
#print (rec_fib(10))
print timeit.timeit("it_fib(n)", number = 1000000)
print timeit.timeit("rec_fib(n)", number = 1000000)
timeit.timeit can take a function or a string. For script use, the function is usually more convenient:
print timeit.timeit(lambda: it_fib(10))
print timeit.timeit(lambda: rec_fib(10))