CRossi
CRossi

Reputation: 61

How do I call a function inside another function in the same file in Python?

I am trying to break up some code into smaller subprograms within the same file to make it more modular. This is the code I would like to break up:

def time():
    print("This program calculates the number of seconds in a given length of 
        time.\n")
    second = 1
    minute = second * 60
    hour = minute * 60
    day = hour * 24
    week = day * 7
    number1 = (eval(input("Enter a number of weeks: ")))
    calc1 = number1 * week
    number2 = (eval(input("Enter a number of days: ")))
    calc2 = number2 * day
    number3 = (eval(input("Enter a number of hours: ")))
    calc3 = number3 * hour
    number4 = (eval(input("Enter a number of minutes: ")))
    calc4 = number4 * minute
    number5 = (eval(input("Enter a number of seconds: ")))
    calc5 = number5 * second
    sum1 = (calc1 + calc2 + calc3 +calc4 + calc5)
    print("\nIn", number1, "week(s),", number2, "day(s),", number3, "hour(s),", 
        number4, "minute(s), and", number5, "second(s), there are", sum1, 
        "second(s).")

It works the way I want it to when it's all together, but I'd like to break it up somewhere along the lines of this:

def count():
    print("This program calculates the number of seconds in a given length of 
        time.\n")
    second = 1
    minute = second * 60
    hour = minute * 60
    day = hour * 24
    week = day * 7

def number():
    number1 = (eval(input("Enter a number of weeks: ")))
    calc1 = number1 * week
    number2 = (eval(input("Enter a number of days: ")))
    calc2 = number2 * day
    number3 = (eval(input("Enter a number of hours: ")))
    calc3 = number3 * hour
    number4 = (eval(input("Enter a number of minutes: ")))
    calc4 = number4 * minute
    number5 = (eval(input("Enter a number of seconds: ")))
    calc5 = number5 * second
    sum1 = (calc1 + calc2 + calc3 +calc4 + calc5)

def time():
    print("This program calculates the number of seconds in a given length of 
        time.")
    count()
    number()
    print("In,", number1, "weeks,", number2, "days,", number3, "hours,", 
        number4, "minutes, and", number5, "seconds, there are", sum1, 
        "seconds.")

time()

The goal is to run time() and have it call count() and number(), so the code for time() isn't as long. (I know the original code isn't that long, but I'm trying to learn how all this works.)

I've had success calling functions within a file before, but only when it was to print a string, and no math was involved. I've tried playing around with parameters and return and googling and even some gnashing of teeth, but to no avail. I keep ending up with errors like this:

Traceback (most recent call last):
  File "<pyshell#525>", line 1, in <module>
    time()
  File "<pyshell#524>", line 4, in time
    number()
  File "<pyshell#522>", line 3, in number
    calc1 = number1 * week
NameError: name 'week' is not defined

I'm new to programming so I'm sure I'm missing something annoyingly simple, but I haven't been able to figure it out on my own and would appreciate any help.

Upvotes: 3

Views: 5624

Answers (3)

stovfl
stovfl

Reputation: 15513

Question: ... within the same file to make it more modular

You don't need a def count() at all.
All values are constant and therefore should be defined so.
There is no need to compute the values over and over again.

You can make it more modular, for instance:

SECONDS = {'s':1, 'm': 1*60, 'h':60*60, 'd':60*60*24, 'w': 60*60*24*7}
def get_input():
    result = {'sum1':0}
    for cat in ['weeks', 'days', 'hours', 'minutes', 'seconds']:
        value = int( input( "Enter a number of {}: ".format(cat) ))
        result[cat] = value
        result['sum1'] += SECONDS[ cat[:1] ] * value
    return result

def time():
    result = get_input()
    print("\nIn, {weeks}, week(s), {days}, day(s), {hours}, hour(s),"
          " {minutes}, minute(s), and, {seconds} second(s), "
          "there are, {sum1} second(s)."\
          .format(**result))

if __name__ == '__main__':
    print("This program calculates the number of seconds in a given length of time.\n")
    time()

It's common, to use always a __main__ entry point.
This gives you the ability to call def get_input() from other python scripts.

Tested with Python: 3.4.2 and 2.7.9

Upvotes: 1

Benjamin Commet
Benjamin Commet

Reputation: 360

So it seems like the big thing you need to learn about is scope. When you declare a variable inside a function, you can only use that variable inside that function. So for example, when you declare week inside of the count function, you can only access the variable "week" when you are inside the function.

If you want to access a variable from anywhere inside a program you need to declare it globally. Here is a working version of your code with the time variables declared globally.

print("This program calculates the number of seconds in a given length of time.\n")
second = 1
minute = second * 60
hour = minute * 60
day = hour * 24
week = day * 7

def number():
    number1 = (int(input("Enter a number of weeks: ")))
    calc1 = number1 * week
    number2 = (int(input("Enter a number of days: ")))
    calc2 = number2 * day
    number3 = (int(input("Enter a number of hours: ")))
    calc3 = number3 * hour
    number4 = (int(input("Enter a number of minutes: ")))
    calc4 = number4 * minute
    number5 = (int(input("Enter a number of seconds: ")))
    calc5 = number5 * second
    sum1 = (calc1 + calc2 + calc3 +calc4 + calc5)
    print("In,", number1, "weeks,", number2, "days,", number3, "hours,",
        number4, "minutes, and", number5, "seconds, there are", sum1,
        "seconds.")

def time():
    print("This program calculates the number of seconds in a given length of time.")
    number()


time()

You need to be careful with global variables as you can run into problems if you use too many of them. Before trying to write more complicated programs I would recommend reading this article that does a good job explaining how scope and namespaces work in python.

Upvotes: 1

panatale1
panatale1

Reputation: 373

You could have your count return a dict, like:

def count():
    times = {'second': 1}
    times['minute'] = times['second'] * 60
    times['hour'] = times['minute'] * 60
    times['day'] = times['hour'] * 24
    times['week'] = times['day'] * 7
    return times

Then you can call count in the time and pass it to number:

def time():
    ...
    times = count()
    values = number(times)



def number(times):
    values = {}
    number1 = int(input("Enter a number of weeks: "))
    calc1 = number1 * times['week']
    values.update({'number1': number1, 'calc1': calc1})
    ...
    sum1 = calc1 + calc2 + calc3 + calc4 + calc5
    values['sum1'] = sum1
    return values

And then you can use the returned dict from number to populate your print at the end of time

Upvotes: 0

Related Questions