使用装饰器的未定义变量

Undefined variable using decorators

我正在尝试编写一个代码,允许人们输入坐标或位置,然后 return 地点名称或地点坐标,显然取决于用户选择输入的内容第一的。我遇到的错误如下: 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()

问题是search_lan = input("Input latitude: ")不会总是被执行,例如如果他们输入location或无效输入。

让我们分解代码的范围。

# 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()

search_lansearch_lon 变量(有时)定义在 global > my_decorator > wrapper 范围内。您正在尝试在 global > some_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()