0

I want to be able to get variables such as dns_float_a that were defined inside the latitude() function object to work outside latitude().

The section of code I'm working with is below. It shows two variable objects defined using def ():. I then want to print the equation at the bottom, but in order to do this I need to reference the variables within the function objects.

PS this is literally the first program I've ever written (it's part of a longer latitude/longitude conversion program) so try don't assume I know much please!

Thanks in advance!

def latitude():
    #LATITUDE
    print "***Degrees/Minutes/Seconds >>> Decimal Degrees***"
    print
    print "Input Latitude"

    dns_a=raw_input("Degrees: ")
    mns_a=raw_input("Minutes: ")
    sns_a=raw_input("Seconds: ")
    ns=raw_input("North (1) or South (2): ")

    dns_float_a=float(dns_a)
    mns_float_a=float(mns_a)
    sns_float_a=float(sns_a)
    ns_float=float(ns)

    #south
    if ns_float==2:
        dns_float_a=dns_float_a*(-1)
        mns_float_a=mns_float_a*(-1)
        sns_float_a=sns_float_a*(-1)
        ns_x="South"

    #north
    elif ns_float==1:
        dns_float_a=dns_float_a*1
        mns_float_a=mns_float_a*1
        sns_float_a=sns_float_a*1
        ns_x="North"

    elif ns_float<1 or ns_float>2 or ns_float>1 and ns_float<2:
        print
        print "*Invalid Input*"
        latitude()

def longitude():
    #LONGITUDE
    print
    print "Input Longitude"

    dns_b=raw_input("Degrees: ")
    mns_b=raw_input("Minutes: ")
    sns_b=raw_input("Seconds: ")
    ns=raw_input("East (1) or West (2): ")

    dns_float_b=float(dns_b)
    mns_float_b=float(mns_b)
    sns_float_b=float(sns_b)
    ns_float=float(ns)

    #south
    if ns_float==2:
        dns_float_b=dns_float_b*(-1)
        mns_float_b=mns_float_b*(-1)
        sns_float_b=sns_float_b*(-1)
        ns_x="South"

    #north
    elif ns_float==1:
        dns_float_b=dns_float_b*1
        mns_float_b=mns_float_b*1
        sns_float_b=sns_float_b*1
        ns_x="North"

    elif ns_float<1 or ns_float>2 or ns_float>1 and ns_float<2:
        print
        print "*Invalid Input*"
        longitude()

latitude()
longitude()

#(d/m/s)ns_float_a
decimal_degrees_latitude=(dns_float_a)+(mns_float_a/60)+(sns_float_a/3600)
#(d/m/s)ns_float_b
decimal_degrees_longitude=(dns_float_b)+(mns_float_b/60)+(sns_float_b/3600)

print
print "Results:"
print
print "Latitude: ", decimal_degrees_latitude
print "Longitude: ", decimal_degrees_longitude
print
martineau
  • 119,623
  • 25
  • 170
  • 301
  • 1
    This is a duplicate. Look [here][1] for the solution. [1]: http://stackoverflow.com/questions/19326004/access-a-function-variable-outside-the-function-in-python-without-using-global – cleros Jan 16 '15 at 22:35
  • 1
    @cleros: I don't think it's a duplicate...or is at least different enough from that other question to warrant not being closed. BTW, to put an inline link in a comment use something like `[Google](http://www.google.com/)`. – martineau Jan 17 '15 at 00:28

3 Answers3

3

This is an issue with scope inside Python. Basically, you can not access variables defined inside of a function outside of the function.

One way to get around this is to pass the variables you need as a return type from the function. This actually can simplify your code since you do not need to have _a and _b for all variables in each function. The scoping rules mean that you can have a variable of the same name in two different functions and they do not override each-other. Add the following line at the end of the latitude and longitude functions:

return dns_float,mns_float,sns_float

Then change the function calls to:

dns_float_a,mns_float_a,sns_float_a = latitude()
dns_float_b,mns_float_b,sns_float_b = latitude()

Alternatively, you could move the latitude and longitude calculations into the functions themselves. Change the last line of each function to:

return dns_float+mns_float/60+sns_float/3600

Then change the function calls to:

decimal_degrees_latitude = latitude()
decimal_degrees_longitude = longitude()
Community
  • 1
  • 1
fizzyh2o
  • 1,237
  • 9
  • 18
  • 1
    In my (and many other folks) option, this approach is better than having functions reference variables in other functions or having them all access (and possibly change) global variables. – martineau Jan 17 '15 at 00:40
2

return values from a function, writing at the end:

return dns_float_a, mns_float_a, sns_float_a

and use outside:

dns, mns, sns = latitude()
Andrew_Lvov
  • 4,621
  • 2
  • 25
  • 31
0

You already have been told how to make data from inside the function available outside.

But you can do even more: as the two functions are nearly identical, you could combine most of them into one generic one.

    class InvalidInputError(ValueError): pass

    def enter_degrees(input_what, pos_string, neg_string):
        print
        print "Input " + input_what
        d_a = int(raw_input("Degrees: "))
        m_a = int(raw_input("Minutes: "))
        s_a = int(raw_input("Seconds: "))
        dir = int(raw_input(pos_string + " (1) or " + neg_string + " (2)"))

        # south or west - negative:
        if dir == 2:
            d_a = -d_a
            m_a = -m_a
            s_a = -s_a
            dir_x = neg_string

        # north or east - positive
        elif ns_float==1:
            dir_x = pos_string
        else:
            raise InvalidInputError("1 or 2!")
        # return d_a, m_a, s_a, dir_x
        return d_a + m_a / 60.0 + s_a / 3600.0

    def enter_degrees_loop(input_what, pos_string, neg_string):
        while True:
            try:
                return enter_degrees(input_what, pos_string, neg_string)
            except InvalidInputError, e:
                print e # output the error
                continue

    def enter_latitude():
        return enter_degrees_loop("Latitude", "North", "South")

    def enter_longitude():
        return enter_degrees_loop("Longitude", "East", "West")

    print "***Degrees/Minutes/Seconds >>> Decimal Degrees***"
    print

    latitude = enter_latitude()
    longitude = enter_longitude()

    print
    print "Results:"
    print
    print "Latitude: ", latitude
    print "Longitude: ", longitude
    print

As you can see, I have made some additional changes:

  • I changed the conversion from float() to int(): it makes no sense to have have non-integers here
  • I have put the print statements where they belong
  • I use an exception to indicate input error and wrap another layer around that all to loop until all was entered correctly
  • I replace d_a * (-1) with -d_a and d_a * 1 with a mere d_a
  • I move the calculation into the innermost function

What still can be done:

  • Check the degrees, minutes and seconds for correct range
  • Omit what is not needed (e. g. dir_x)
glglgl
  • 89,107
  • 13
  • 149
  • 217