0

So here is my entire code, I am having trouble when it says height is not defined in window_Calculate(). My aim is to use the formula 50 + (height * width) * 100. In window_Size, the user must input a height and width but if they type anything that is not a number, it is supposed to return it so they can enter in an actual number. Overall, height is not defined while in a different function and does not return back to the input if user enters anything but numbers. How can I make height defined and return back to the input?

import time 

def Intro():
    print("Welcome to Wendy's Windows.")
    time.sleep(2)
    print("This is a window replacement business.")
    time.sleep(2)
    print("Enter your size in the box on the left and the price will be displayed below.")
    time.sleep(2.5)

def window_Size():
    print("Put height first then put width.")
    time.sleep(1.5)
    height = input("Height: ")
    try:
        int(height)
    except ValueError:
         try:
            float(height)
         except ValueError:
            print("Enter only numbers.")
            return(height)
    else:
        print(height + "m")
    width = input("Width: ")
    try:
        int(width)
    except ValueError:
        try:
            float(width)
        except ValueError:
                print("Enter only numbers.")
                return(width)
    else:
        print(width + "m")

def window_Calculate():
    window_Calculate = '50' + (height * width) * '100'

def window_Cost():
    print("Your price is" + window_Calculate + "$")

window_Size()
window_Calculate()
window_Cost()
kaza
  • 2,317
  • 1
  • 16
  • 25
Beatenberg
  • 15
  • 8
  • Well you call `window_Calculate()` and you called `return(height)` in `window_Size()` but you never put it into something. – pstatix Sep 08 '17 at 02:34

3 Answers3

2

So there are a couple things here:

  1. window_Size()'s try/except type testing
  2. window_Size() calling return(height) but not storing it
  3. window_Calculate() using a non-local variable but given no parameters

What you are attempting at doing is using what is known as a global variable. In just about any programming language, their use is not encouraged. Rather, you should use a local variable that is scoped within a called function that return the variable back to the higher calling function.

Below I have pointed out some highlights in your program, as well as given a rendition of your program with the changes. Though a solution, I am unfamiliar with how much you understand about the concepts, so it is only a slight modification to your program to make the points clear. This can however be altered significantly to be more pythonic and refined.

Number 1:

def window_Size():
    print("Put height first then put width.")
    time.sleep(1.5) # bit annoying to sleep all the time?
    height = input("Height: ")
    try:
        int(height) # type test of int, that's fine
    except ValueError: # correct catch
         try:
            float(height) # type test of float, that's fine
         except ValueError: # correct catch; must be invalid
            print("Enter only numbers.") # message for user
            return(height) # wait why did you return??
    else: # wont be executed if above return() is called (i.e. for str())
        print(height + "m")
    width = input("Width: ")
    try:
        int(width)
    except ValueError:
        try:
            float(width)
        except ValueError:
                print("Enter only numbers.")
                return(width) # All the same notes above apply
    else:
        print(width + "m")

So you are using a try/except/else which is perfectly fine, but you have 2 return() calls in a single function; as soon as one is called, window_Size() will exit (i.e. without a width if return(height) is called. Further, to return multiple values, you can use a tuple.

Number 2:

window_Size() # this functions returns values, but isnt storing

Number 3:

window_Calculate() # this functions uses returns values, but isnt passed any

Solution:

import time 

def intro():
    print("Welcome to Wendy's Windows.")
    time.sleep(2) # personally I'd get rid of all time.sleep() calls
    print("This is a window replacement business.")
    time.sleep(2)
    print("Enter your size in the box on the left and the price will be displayed below.")
    time.sleep(2.5)
    process_customer()

def process_customer():
    size = window_size()
    # get rid of window_calculate() all together
    total = window_cost(size)
    print("Your price is" + str(total) + "$")

def window_size():
    print("Put height first then put width.")
    while True:
        height = input("Height: ")
        try:
            h = int(height)
            break
        except ValueError:
             try:
                h = float(height)
                break
             except ValueError:
                print("Enter only numbers.")
    print(height + "m")
    while True:
        width = input("Width: ")
        try:
            w = int(width)
            break
        except ValueError:
            try:
                w = float(width)
                break
            except ValueError:
                print("Enter only numbers.")
    print(width + "m")
    return h, w

def window_cost(size):
    return 50 + (size[0] + size[1]) * 100 # before 50 and 100 were str()

intro()
pstatix
  • 3,611
  • 4
  • 18
  • 40
  • Upvoted for being the only answer not suggesting globals. – GManNickG Sep 08 '17 at 02:58
  • @GManNickG Thanks for the catch! I saw the other answers rolling in and was trying to catch up! I've done the `tuple` return but isnt that only a Python 3 implementation? I prefer generally to send a solid container back honestly. – pstatix Sep 08 '17 at 02:58
  • @GManNickG Huzzah for vanquishing the misuse of globals! – pstatix Sep 08 '17 at 02:59
  • Tuple expressions have been in the language for a long time. :) Tuples *are* a container. In fact, they are better than lists for things like this because they are immutable. – GManNickG Sep 08 '17 at 03:00
  • @GManNickG Oh I know tuples have been, I meant the `return val1, val2` syntax. I thought that came in with Python 3. Before Python 3 you had to supply a pre-built container to return multiple variables. Right? I swear I read that somewhere. – pstatix Sep 08 '17 at 03:01
  • 1
    Nope, AFAIK Python 1.0 had this syntax. – GManNickG Sep 08 '17 at 03:04
  • @pstatix When I input your code it comes up with TypeError: unsupported operand type(s) for +: 'int' and 'str' – Beatenberg Sep 12 '17 at 04:39
  • @Beatenberg So I changed a couple things. In each `try/except` a new local variable `h` or `w` is defined and initialized during type testing. The `input()` function returns a `str` type, so if you called `int(height)` on say `'20'`, the conversion would take place on that line, but the `height` variable will still be `'20'`. If some problem persists, please post the full stack trace. – pstatix Sep 12 '17 at 10:49
-1

you should make sure that height,width,and window_Calculate are global variables,so you could change them in A function,and use them in B function.

colt
  • 1
  • 1
  • 2
    One should try to avoid global variables because they are [evil](https://stackoverflow.com/questions/19158339/why-are-global-variables-evil). Constants on the other hand are perfectly fine to be declared globally. – pstatix Sep 08 '17 at 02:54
-1

pstatix's answer is the best solution and should be accepted

you need to have "global" variables each method can get or set. try this:

import time 

window_height = 0
window_width = 0
window_value = 0

def Intro():
    print("Welcome to Wendy's Windows.")
    time.sleep(2)
    print("This is a window replacement business.")
    time.sleep(2)
    print("Enter your size in the box on the left and the price will be displayed below.")
    time.sleep(2.5)

def window_Size():
    global window_height
    global window_width
    print("Put height first then put width.")
    time.sleep(1.5)
    height = input("Height: ")
    try:
        int(height)
    except ValueError:
         try:
            float(height)
         except ValueError:
            print("Enter only numbers.")
            return(height)
    else:
        print(str(height) + "m")
        window_height = height
    width = input("Width: ")
    try:
        int(width)
    except ValueError:
        try:
            float(width)
        except ValueError:
                print("Enter only numbers.")
                return(width)
    else:
        print(str(width) + "m")
        window_width = width

def window_Calculate():
    global window_value
    window_value = 50 + window_height * window_width * 100

def window_Cost():
    print("Your price is $" + str(window_value))











window_Size()
window_Calculate()
window_Cost()
axelspark
  • 198
  • 10
  • 2
    One should try to avoid global variables because they are [evil](https://stackoverflow.com/questions/19158339/why-are-global-variables-evil). Constants on the other hand are perfectly fine to be declared globally. – pstatix Sep 08 '17 at 02:54
  • global variables may not be the best implementation and it is a good practise to avoid but it is definitely a stretch to say they are evil. there is a reason why they persist over many iterations of Python. paraphrasing the 4th paragraph of your link's answer: limited usage of globals are acceptable especially for simplicity's sake and easier comprehension. – axelspark Sep 08 '17 at 03:19
  • @axelspark: This is not one of those cases. Returning values from functions is the purpose of functions, so do that. – GManNickG Sep 08 '17 at 03:39