Как исправить ошибку «NoneType» с помощью декораторов Python? - PullRequest
1 голос
/ 30 июня 2019

Я делаю кэш LRU (Least недавно Used) с декоратором для хранения недавно использованной локализации, но когда я вызываю функцию, чтобы прочитать ее из файла .json, я получаю ошибку «NoneType»

def loc_cache(func):
    loc_cache.locale = {} # {lang:(local, count)} local:dict
    loc_cache.MAXLENGTH = 5
    def wrapper(key):
        print(key) #this function wasn't called
        if key not in loc_cache.locale.keys():
            try:
                locale = read_locale(key)
                loc_cache.locale[key] = (locale, 1)
                wrapper.locale = locale
            except KeyError:
                key = "en" # set default locale
                wrapper(key)
        else:
            locale, count = loc_cache.locale[key]
            loc_cache.locale[key] = (locale, count+1)
            wrapper.locale = locale
        return wrapper.locale

@loc_cache
def read_locale(key):
    locale = read_json("./config/locale.json", key)
    return locale

def auth(user:User):
    locale = read_locale(user.locale)
    print(locale["auth"])
    return

u = User(1) # __init__ takes 1 for id
u.locale = "en"
auth(u)

Я ожидаю, что он вернет фразу в «en», которая хранится в файле .json, но там написано

Traceback (most recent call last):
  File "main.py", line 61, in <module>
    auth(u)
  File "main.py", line 52, in auth
    locale = read_locale(user.locale)
TypeError: 'NoneType' object is not callable

Ответы [ 2 ]

2 голосов
/ 30 июня 2019

Вы не вернули функцию-обертку из декоратора, поэтому Python возвращает None как обычно и пытается вызвать ее, когда вы делаете read_locale(user.locale). Вам нужно:

def loc_cache(func):
    loc_cache.locale = {} # {lang:(local, count)} local:dict
    loc_cache.MAXLENGTH = 5
    def wrapper(key):
        print(key) #this function wasn't called
        if key not in loc_cache.locale.keys():
            try:
                locale = read_locale(key)
                loc_cache.locale[key] = (locale, 1)
                wrapper.locale = locale
            except KeyError:
                key = "en" # set default locale
                wrapper(key)
        else:
            locale, count = loc_cache.locale[key]
            loc_cache.locale[key] = (locale, count+1)
            wrapper.locale = locale
        return wrapper.locale
    return wrapper
    # Here ^^^^
0 голосов
/ 30 июня 2019

Вы не вернули ваш wrapper в конце декоратора:

def loc_cache(func):
    loc_cache.locale = {} # {lang:(local, count)} local:dict
    loc_cache.MAXLENGTH = 5
    def wrapper(key):
        if key not in loc_cache.locale:
            try:
                locale = read_locale(key)
                loc_cache.locale[key] = (locale, 1)
            except KeyError:
                key = "en" # set default locale
                wrapper(key)
        else:
            locale, count = loc_cache.locale[key]
            loc_cache.locale[key] = (locale, count+1)
        wrapper.locale = locale
        return wrapper.locale
    <b>return wrapper</b>

Декоратор обычно принимает в качестве входных данных функцию и возвращает функцию.Здесь вы определили внутреннюю функцию, но забыли ее вернуть.В результате на выходе декоратора будет None, и вы не сможете позвонить на None.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...