Multiple Questions About My Final Code


#1

When doing the courses I always try to go into more dept than what’s asked using everything that’s been taught before / stuff I found online. Though it makes for a more enjoyable learning experience (imo) it also leaves me with more questions. See below my final piece of functional code, after which I’ve put all the questions that came to mind.

def hotel_cost(nights):
  print "Hotel Cost: $%s" %(CostPerNight*nights)
  return (CostPerNight * nights)

def plane_ride_cost(city):  
  if city == "Charlotte" or city =="Ch":
    flight_cost = 183
  elif city in ("Tampa","Ta"):
    flight_cost = 220
  elif city in ("Pittsburgh", "Pb"):
    flight_cost = 222
    return flight_cost
  elif city in ("Los Angeles", "LA"):
    flight_cost = 475
  else:
    flight_cost = 0
    print "Destionation Entered is not present in database thus flight cost is unknown."
  print "Destination: %s" %city
  print "Flight Cost: $%s" %flight_cost
  return flight_cost

def rental_car_cost(days):
  car_cost = 40 * days
  if days >= 7:
    car_cost -= 50
  elif days >= 3:
    car_cost -= 20
  print "Car Cost: $%s" % (car_cost)
  return car_cost

def trip_cost(city,days,spending_money):
  return sum([plane_ride_cost(city), rental_car_cost(days), hotel_cost(days-1),spending_money])
    


CostPerNight = 140
Location = raw_input("""Where Do You Wanna Go?
""")
N = int(raw_input("""For how many days do you want to go to %s?
""" % (Location)))
spend = (N*int(raw_input("""How much money are you willing to spend a day?
""")))
print "Your Total Budget For Additional Costs is: $%s" % (spend)

"""This was used before the function total_cost called these same functions
plane_ride_cost(Location)
rental_car_cost(N)
hotel_cost(N-1)"""

print "Total Cost: $%s" % (trip_cost(Location,N,spend))

The main ways of how my code differs from what the course asked is that it gives feedback to the console using print here and there and that some of the variables are not set but instead it’s value is asked in the console using the raw_input.

My questions:

After moving some code (Ctrl+X Ctrl+V) I suddenly started typing at two lines at the same time, which I imagine can be useful at times. How do you toggle that?

Initially I had placed the return of the flight costs within all if / elif statements, which resulted in the final console feedback after the conditional coding was not being executed. After some testing I noticed that placing return at the end of the function, instead of within the if statements, solved the issue. Is this because return ended the function prematurely? Does return always immediately end a function?

As you can see I used two different ways of checking for the alternative (abbreviated) versions of the same locations. I had found three ways to do this so far, or (which has been taught in a previous CodeCademy lesson), in (as used here) and is. I felt like in was the most appropriate operator in this as it looks the most ‘neat’ as well as allowing for an easier addition of extra abbreviations. (would you agree? why (not)?).

Something else that feels a bit inefficient is the fact that I got both a Location variable as well as a City argument, which are equal as defined. Would there be a way to combine these to use just one name and thus be a bit neater as well as using less NameSpace?
Furthermore both the function trip_cost and plane_ride_cost / rental_car_cost use the same arguments, why does this not cause any trouble?

I am using sum to add together all individual costs in trip_cost, and read that you could use a iterable before the square brackets. What is a iterable and more importantly what does it do in this context? (already tried to learn what’s by searching, I think its use here will make that clearer)

What is the advantage of using the individual functions when finding the trip_cost as opposed to using some of the variables which are equal to the returned value?

Finally, I have put the variables / the raw_inputs for the variables below the functions themselves. Is this the ‘correct’ way to do this or should I start putting the variables used in a function above the functions themselves?
I understand that the variables should always be defined before using the functions.

Those are my questions, but please feel free to comment on anything else you feel like could be done better!

A link to the lesson: https://www.codecademy.com/courses/learn-python/lessons/taking-a-vacation/exercises/plan-your-trip?action=resume_content_item note: the suggested solution is quite different from my code and probably will not help you answer my questions. Also not the my code does not pass the SCT (anymore) as it is too different.


#2

Not prematurely, definitively and deliberately. return is akin to exit.

One question I have, what if all we want to from trip_cost is a number, as in total cost. All that verbosity along the way rather defeats this discreet action.

As hinted above, if the functions are not verbose, but rather discreet, and only return a value (as one might expect), then all the verbosity can be enclosed in a Summary. That is where individual calls can be made and their returns inserted into the verbose report, and kept on the side for the final tally.

Programming is not subjective, but objective. There are many ways to perform the same task, and it is not at all arbitrary, but a matter of choosing one and working with it. Provided the outcome is what we expect with no anomalies, false positives or edge cases the code is reasonably acceptable.

Refactoring for readability or optimal performance is something we can do to further study our code, our logic, our writing style, and the overall usability of the program.

Either is acceptable, except for the arbitrary abbreviations in both. As plane flights go, every city (airport, actually) has an international three letter code. For instance ‘Edmonton’ is YEG. That would be more appropriate for matching since it makes perfect sense and is not arbitrary. Not everyone thinks alike, that’s why we have international standards in areas such as air travel.


#3

you can shift or ctrl + left mouse click to achieve this. It depends on the editor you use. It might vary for editor in use.

yes, given return is the last thing a function does. By default a function returns None:

def example():
   print "example"

print example()

using a print statement on example function call, we can print the returned result (which is None)

point 3, is test for identity, so its not viable here. Worrying to much about small optimizations can cost a lot of time, both in and or are fine. I don’t think it represents a real word applications, then the user would very likely pick destinations from a database (with its associated cost in the same table row), so the whole design is different.

city is only a local variable, so its not problem. In fact having the same name would be confusing, you can loose track of what value belongs to which variable

sum is a built-in function which gives the sum of an iterable, but given the values are all integers and not yet a list, i would just use + to add integers together and get rid of sum. Not sure why you want to get from integer to list and then back to integer. Seems unnecessary.

functions should only do a single thing, it makes the code more maintainable, flexible, easier to read and test.

i would have made a separated function to get the user inputs (to not pollute global name space)

and instead of 3 print statements in a row, i would simply use a multiline string:

https://stackoverflow.com/questions/10660435/pythonic-way-to-create-a-long-multi-line-string

that will much more improve readability then debating over or or in


#4

I actually read it to mean there is no return value so on return to the caller, in absence of same the interpreter reports None if there is more interaction with the result of the function call.

def foo():
    pass

print (foo())            # None

print (foo() or True)    # True

#5

@mtf

That’s a fair point. I’ll aim to put print statements like these outside of the functions itself in the future.

This is fair and definitely a more ordered way to code, but how does that affect whether we’re using a variable equal to the returned value or the function itself? I’d feel like a variable is preferred (given that NameSpace is not an issue) as you would not be running the function again thus putting less strain on the Machine, would you agree?

As to my arbitrary abbreviations, because they indeed are quite arbitrary, I understand that International airport codes are better in an actual program.

@stetim94

I see, am I correct to note that as city is only a local variable it does not use any NameSpace (outside of the function), therefore you could have another variable by the name city somewhere else in the program? Does this also mean one could have multiple functions with the same local variable? E.g.

f(x):
  y1 = x + 2
  return y1
g(x):
  y2 = x**2
  return y2
h(x):
  y3 = 2**x
  return y3

That makes two of us! I did not know the sum function converts integers to lists.

How does using the variable equal to the return make the function do more than one thing?

Thank y’all for your answers, have a good day!


#6

yes, you can. But more importantly, variable should have logic variable names

you converted to list:

# this code creates a list
[plane_ride_cost(city), rental_car_cost(days), hotel_cost(days-1),spending_money]

of course the values inside the list are still integers, so conversion might not have been the right word, but you add a list unnecessary, that is not sums doing. The point that the list is unnecessary still stands.

no, its about separating logic. This makes the code a lot easier to work with. Now we can test separate parts of the program (the hotel_cost, trip_cost and car_ride function) using unit tests and test the program as a whole (integrity test of the whole code by testing trip_cost function)

if you stuff everything within a single function, testing becomes more difficult, which means the code quality is reduced, making the code more difficult to maintain, robust and easier to change (if that need arises)


#7

This program will never be a strain on the machine. It’s always running, anyway. If it was recursive or used a lot of memory, that would affect the performance, which would be a concern. The only enemies the machine has are dust and heat.

Small, simple, re-usable functions are how we organize our logic and break down larger tasks into smaller ones. In this program we have four such functions that each have a specific role in the larger body.

hotel_cost()
plane_ride_cost()
rental_car_cost()
trip_cost()

When we give those roles only the bare essential code then testing and using the program becomes simpler and the outcomes more predictable. Each of the above functions imply a single value in the return. Even when expanding the overall role of the program (user inputs, screen reports, summary) we will never have to touch those functions. Their job is clearly defined and will never change. That makes for an easier program to maintain and update.


#8

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.