Does return finishes a function on Python? - python

I'm learning on codeacademy and I was trying to print the following:
def trip_cost(p, d, m):
return rental_car_cost(d) + hotel_cost(d) + plane_ride_cost(p) + m
print "%s to %s for %s days with an extra %s dollars of spending mone" (trip_cost(p, d, m), p, d, m)
The program was telling me nothing was printing on the console, so I proceeded to delete the return line and it worked, so I was wondering if every time a function reaches a return it finishes, in that case in the following code I could've save the "and days < 7" ??
def rental_car_cost(days):
cost = days*40
if days >= 7:
cost -= 50
return cost
elif days >= 3 and days < 7:
cost -= 20
return cost
print cost

so I was wondering if every time a function reaches a return it finishes
Yes, it returns to what called it, hence the name.
in that case in the following code I could've save the and days < 7
Yes. Also you could have left it out because elif means "else if" so even if you didn't return that case would only have been considered if the previous if had been false so that it is considered else.
Generally we call the code and days < 7 here redundant. It's a good idea to remove redundant code. If redundancy makes something clearer then there's little harm leaving it in, but as a rule redundancy is more likely to confuse someone than to assist them, especially when you get more familiar with the language.

Yes, you can leave out and days < 7

Yes, return finishes the function and nothing else after that line is executed. Your example will work fine for the if-elif-else statements, as the appropriate condition will be checked and executed, returning the corresponding cost.
As a tip, you can use elif 3 <= days < 7 instead of elif days >= 3 and days < 7. Python is nice like that! In the way your conditions are structured, you can just have elif days >=3.

Related

Testing multiple conditions with a Python if statement

I am trying to get into coding and this is kinda part of the assignments that i need to do to get into the classes.
In this task, you will implement a check using the if… else structure you learned earlier.You are required to create a program that uses this conditional.
At your school, the front gate is locked at night for safety. You often need to study late on campus. There is sometimes a night guard on duty who can let you in. You want to be able to check if you can access the school campus at a particular time.
The current hour of the day is given in the range 0, 1, 2 … 23 and the guard’s presence is indicated by with a True/False boolean.
If the hour is from 7 to 17, you do not need the guard to be there as the gate is open
If the hour is before 7 or after 17, the guard must be there to let you in
Using predefined variables for the hour of the day and whether the guard is present or not, write an if statement to print out whether you can get in.
Example start:
hour = 4
guard = True
Example output:
'You're in!'
Make use of the if statement structure to implement the program.
One of my ideas was:
Time = int(input("Time of getting in: "))
open = 7
closed = 17
if Time > open and Time < closed:
print("You can not enter")
cap O will solve
Time = int(input("Time of getting in: "))
Open = 7
closed = 17
if Time > Open and Time < closed:
print("You can not enter")
It's not too difficult, you can do a simple function like that :
def go_to_study(hour, start_day = 7, end_day = 17):
if (hour >= start_day and hour <= end_day):
return True
else:
return False
// on one line, uncomment if you want.
// return (hour >= start_day and hour <= end_day)
hour=int(input("Enter the Hour"))
if hour>=7 and hour<=17:
print("You can Go")
else:
print("You need Guard to let you in")

Why can I not use two 'if-statements' rather an elif, if only one of the two will execute?

I am writing code to solve a basic problem:
def is_leap(year):
leap = False
if year % 4 == 0:
if year % 100 == 0 and year % 400 != 0:
leap = False
if year % 100 == 0 and year % 400 == 0:
leap = True
else:
leap = True
return leap
print(is_leap(2100))
My question is with regards to the inner most scope; specifically for the second 'if statement'- I know this must be an 'elif' (and if we don't change it, our answer will be wrong) but I don't see why this is the case.
In my IDE, if I leave the code as is above, the 'leap=False' for the first if statement greys out.
Even though I understand if vs elif generally, why can we not just have both as 'if statements'? Because (in this case) based on the logic, for any input we use as an argument, only one of the two if statements will be executed right?
elif's do not execute if the if condition is correct. If you use two if statements no matter what they both would be executed.
Not just that, since you have an else, the else would only be connected to the second if condition, whereas an elif would connect the entire block of code.

Replacing Iteration with Recursion Python [duplicate]

This question already has answers here:
Is this function recursive even though it doesn't call itself?
(3 answers)
Closed 5 years ago.
I'm just starting to learn about recursion for an EdX course, and I've written an iterative function to calculate the remaining balance after paying the minimum required payment for 12 months.
I was able to easily do it with iteration, but I can't seem to wrap my head around the recursive way.
Please point me in the right direction.
Here is my iterative function
def remaining_balance_iter(balance,annualInterestRate, monthlyPaymentRate ):
'''
This code will take any balance and annual interest rate and calculate the
balance after one year of making the minimum payments
'''
month = 1
monthly_interest_rate = annualInterestRate/12.0
while month <= 12:
minimum_monthly_payment = monthlyPaymentRate * balance
monthly_unpaid_balance = balance - minimum_monthly_payment
balance = monthly_unpaid_balance + monthly_interest_rate*monthly_unpaid_balance
print( "Month {} Remaining balance: ".format(month) + str(round(balance,2)))
month += 1
print ("Remaining balance " + str(round(balance,2)))
I've made an attempt at a recursive function, but it needs work, and I need tutoring haha
def remaining_balance_recur(balance,annualInterestRate, monthlyPaymentRate, month ):
'''
This code will take any balance and annual interest rate and calculate the
balance after one year of making the minimum payments
'''
month = 1
monthly_interest_rate = annualInterestRate/12.0
while month <= 12:
minimum_monthly_payment = monthlyPaymentRate * balance
monthly_unpaid_balance = balance - minimum_monthly_payment
interest = monthly_interest_rate*monthly_unpaid_balance
balance = remaining_balance_recur(monthly_unpaid_balance, annualInterestRate, monthlyPaymentRate, month + 1) + interest
print ("Remaining balance " + str(round(balance,2)))
The best way I've found to deal with recursion is to start by specifying a base case. What is the condition that tells you when you've finished your method? In your code, it looks like you run your method until `month > 12', so your base case would be:
if month > 12:
return 1 # 1 for the purpose of explanation
Your return value for your base case is some base value of your function. What would your script return if your month was 12? That's the value you would return.
Next is the hard part. You have to figure out what variable is being modified by subsequent calls to your method. I'm not exactly sure what your code is intended to do, but it looks like you have a few calculations on some variables. When you use recursion, it's almost as if you're saving the state of the current method call you are executing while you go and retrieve the value you need for your statement. (e.g. a_num = 1 + recurse(n - 1) - you need the value of recurse(n - 1) before you can continue with this statement. This is only an example, though). Look for the variable that is affected by your previous iterations and try to make that recursive. In your situation, it looks like balance is that variable:
balance = balance + remaining_balance_recur(annualInterestRate, monthlyPaymentRate, month + 1)
return balance
When you write a recursive method, you always need to return some value at the end of the method, so the statement that called the method actually gets a value. Here's a short, useless example:
def recurse(n)
if n == 0 # BASE CASE
return 1
some_sum = 0
some_sum += recurse(n - 1) # I need the value from recurse(n - 1)
return some_sum # This method was called somewhere, so it needs to return
Try to figure out a recursive solution for your code from these hints. I'm sorry, recursion is very hard to explain especially over SO. Youtube vids and Google would also be a big help to understand recursion in general. Hope this gave you some ideas.
By putting "month = 1" before the while statement, you are resetting it so that while month <= 12 will run forever. This creates a "RecursionError: maximum recursion depth exceeded in comparison."
The output of your function is currently "NoneType" because its output is a print statement rather than returning an int or a float. This produces a "TypeError" because you have tried to add a float (the interest rate) to a NoneType (the printed statement) in your recursion.

Using return instead of yield

Is return better than yield? From what ive read it can be. In this case I am having trouble getting iteration from the if statement. Basically what the program does is take two points, a begin and end. If the two points are at least ten miles apart, it takes a random sample. The final if statement shown works for the first 20 miles from the begin point, begMi. nCounter.length = 10 and is a class member. So the question is, how can I adapt the code to where a return statement would work instead of a yield? Or is a yield statement fine in this instance?
def yielderOut(self):
import math
import random as r
for col in self.fileData:
corridor = str(col['CORRIDOR_CODE'])
begMi = float(col['BEGIN_MI'])
endMi = float(col['END_MI'])
roughDiff = abs(begMi - endMi)
# if the plain distance between two points is greater than length = 10
if roughDiff > nCounter.length:
diff = ((int(math.ceil(roughDiff/10.0))*10)-10)
if diff > 0 and (diff % 2 == 0 or diff % 3 == 0 or diff % 5 == 0)\
and ((diff % roughDiff) >= diff):
if (nCounter.length+begMi) < endMi:
vars1 = round(r.uniform(begMi,\
(begMi+nCounter.length)),nCounter.rounder)
yield corridor,begMi,endMi,'Output 1',vars1
if ((2*nCounter.length)+begMi) < endMi:
vars2 = round(r.uniform((begMi+nCounter.length),\
(begMi+ (nCounter.length*2))),nCounter.rounder)
yield corridor,begMi,endMi,'Output 2',vars1,vars2
So roughdiff equals the difference between two points and is rounded down to the nearest ten. Ten is then subtracted so the sample is taken from a full ten mile section; and that becomes diff. So lets say a roughDiff of 24 is rounded to 20, 20 - 10, diff + begin point = sample is taken from between mi 60 and 70 instead of between 70 and 80.
The program works, but I think it would be better if I used return instead of yield. Not a programmer.
return is not better, it's different. return says "I am done. Here is the result". yield says "here is the next value in a series of values"
Use the one that best expresses your intent.
Using yield makes your function a generator function, which means it will produce a series of values each time its (automatically created) next() method is called.
This is useful when you want to process things iteratively because it means you don't have to save all the results in a container and then process them. In addition, any preliminary work that is required before values can generated only has to be done once, because the generator created will resume execution of your code following the that last yield encountered — i.e. it effectively turns it into what is called a coroutine.
Generator functions quit when they return a value rather than yield one. This usually happens when execution "falls off the end" when it will return None by default.
From the looks of your code, I'd say using yield would be advantageous, especially if you can process the results incrementally. The alternative would be to have it store all the values in a container like a list and return that when it was finished.
I use yield in situations where I want to continue iteration on some object. However, if I wanted to make that function recursive, I'd use return.

What is the best way to write a function that converts an integer of minutes into a string formatted in "X hour(s) Y minute(s)"?

I currently have my Django custom template filter like this:
from django import template
register = template.Library()
#register.filter
def duration(value):
hours = value / 60
minutes = value % 60
hours_string = str(hours) + (" hours" if hours > 1 else " hour" ) if hours else ""
minutes_string = str(minutes) + (" minutes" if minutes > 1 else " minute") if minutes else ""
return ' '.join("{hours} {minutes}".format(hours=hours_string, minutes=minutes_string).split())
Some possible outputs:
1 hour 25 minutes
2 hours
45 minutes
3 hours 1 minute
The ' '.join(....split()) trick was something I got from this solution. I realize I only need to check for the extra string at either the beginning or the end of the string (for when it's 0 hours or 0 minutes), but it seems to do the trick and maybe it's easier to read than regular expression to some people.
I also feel that I am violating DRY since I am repeating almost the exact same if-then block twice. I was thinking of something like...
for i, unit in enumerate([hours, minutes]):
# Do some code.
return ' '.join("{hours} {minutes}".format(hours=value[0], minutes=value[1]).split())
but I couldn't figure out how to choose between "hour(s)" or "minute(s)" without another if-then block. Also the two short-hand if-then per line also looks a bit ugly too...
I'll appreciate any suggestions or tips. Thanks!
import datetime
def pprint(val):
if val == 1:
return '1 minute'
x = str(datetime.timedelta(minutes=val))[:-3].split(':')
r = ''
if int(x[0]):
r += x[0]+' hours' if int(x[0]) > 1 else x[0]+' hour'
if int(x[1]):
r += ' %s minutes' % int(x[1]) if int(x[1]) > 1 else ' %s minute' % int(x[0])
return r.strip()
Sample run:
>>> pprint(65)
'1 hour 5 minutes'
>>> pprint(1)
'1 minute'
>>> pprint(60)
'1 hour'
>>> pprint(61)
'1 hour 1 minute'
You can easily expand this to include days as well, but since you specifically mentioned only hours and minutes I adjusted the method.
The main heavy lifting is done by datetime.timedelta, the rest is just string parsing.
I use this for modular unit conversions, including the sort you've described. I wrote it while working for UCI, and UCI gave permission to distribute it under a specific opensource license:
http://stromberg.dnsalias.org/~strombrg/modunits/
You can use it as a shell-callable for POSIX shell scripts, or it can be used as a python module via import.
I consider it production-quality, and indeed use it in a production role (backups) regularly.
This is my very first attempt at Python, so if this is totally missing your actual goal or is wrought with errors, lemme know and I'll delete.
To keep things DRY, and to eliminate the output of "0 hours" or "1 minutes", this should work, so long as we accept the premise that the base unit (in this case minute and hour) can be pluralized by simply adding an 's'. Anything more complex and you'll want a python ninja:
def format_output(value, unit):
if value == 0:
return ""
singular_output = str(value) + " " + unit
if value == 1:
return singular_output
elif value > 1:
return singular_output + "s"
def duration(value):
hours = value // 60
minutes = value % 60
formatted_string = format_output(hours, "hour") + " " + format_output(minutes, "minute")
return formatted_string.strip()
The one condition the above does not account for is if duration is 0 or blank, which I think should return "0 minutes", but that is an easy fix that is best left to your needs.
Also, I added in the strip() method, otherwise you'll be left with leading or trailing space if one of the two units comes out to zero.

Categories

Resources