Walnut
Walnut

Reputation: 51

Undefined variable using decorators

I am trying to write a code that will allow person to enter either coordinates or location, which then would return either name of the place or coordinates of the place, obviously depending on what user chose to enter first. The error I came across following error: NameError: name 'search_lan' is not defined Error comes up under some_funcion() on url variable

import json
import requests

def my_decorator(some_function):
    def wrapper():
        question = input("Would you like to input coordinates or location?")
        if question == 'coordinates':
            search_lan = input("Input latitude: ")
            search_lon = input("Input longtitude: ")
        elif question == 'location':
            search_place = input("Input address: ")
        else:
            print("Wrong input")
        some_function()

        return search_place, search_lan, search_lon
    return wrapper

api_key = 'api_key_here'




@my_decorator
def some_function():
   url = requests.get('https://maps.googleapis.com/maps/api/geocode/json? 
   latlng={},{}&key={}'.format(search_lan,search_lon,api_key))

   data = json.loads(url.content)

   formatted_address = data['results'][0]['formatted_address']
   print(formatted_address)

some_function()

Upvotes: 1

Views: 1221

Answers (2)

Remco Haszing
Remco Haszing

Reputation: 7829

Lets break down the scopes of your code.

# Scope: global
import json
import requests

def my_decorator(some_function):
    # Scope: global > my_decorator
    def wrapper():
        # Scope: global > my_decorator > wrapper
        question = input("Would you like to input coordinates or location?")
        if question == 'coordinates':
            search_lan = input("Input latitude: ")
            search_lon = input("Input longtitude: ")
        elif question == 'location':
            search_place = input("Input address: ")
        else:
            print("Wrong input")
        some_function()

        return search_place, search_lan, search_lon
    return wrapper

api_key = 'api_key_here'


@my_decorator
def some_function():
    # Scope: global > some_function
    url = requests.get('https://maps.googleapis.com/maps/api/geocode/json? 
    latlng={},{}&key={}'.format(search_lan,search_lon,api_key))

    data = json.loads(url.content)

    formatted_address = data['results'][0]['formatted_address']
    print(formatted_address)

some_function()

The search_lan and search_lon variables are (sometimes) defined in the global > my_decorator > wrapper scope. You’re trying to use them in the global > some_function scope, which is not a child scope of the first one. This means those variables are not defined.

What you probably want to do is pass the variables defined in the decorator wrapper into the decorated function.

import json
import requests

# fn is the decorated function, in this case fn.
def my_decorator(fn):
    def wrapper():
        question = input("Would you like to input coordinates or location?")
        # Make sure these variables are always defined, as they are used later.
        search_lan = None
        search_lon = None

        if question == 'coordinates':
            search_lan = input("Input latitude: ")
            search_lon = input("Input longtitude: ")
        elif question == 'location':
            # This is not handled, but you’ll get the idea.
            search_place = input("Input address: ")
        else:
            print("Wrong input")
        return fn(search_lan, search_lon)
    return wrapper

api_key = 'api_key_here'


# search_lan and search_lon are passed by my_decorator.
@my_decorator
def some_function(search_lan, search_lon):
    url = requests.get('https://maps.googleapis.com/maps/api/geocode/json? 
    latlng={},{}&key={}'.format(search_lan,search_lon,api_key))

    data = json.loads(url.content)

    formatted_address = data['results'][0]['formatted_address']
    print(formatted_address)

some_function()

Upvotes: 2

RealPawPaw
RealPawPaw

Reputation: 986

The issue is search_lan = input("Input latitude: ") will not always be executed, such as if they input location or invalid input.

Upvotes: 0

Related Questions