Декорированная функция возвращает «Нет» - PullRequest
1 голос
/ 07 апреля 2019

Я чрезвычайно новичок в python, и я только что столкнулся с декораторами. Я все еще смущен ими, но я учусь

Я пытался создать декоратор, который сообщит мне, сколько времени ушло на выполнение моей функции, но, очевидно, когда я пытаюсь использовать ее в функции, которая должна что-то возвращать, он просто возвращает «Нет»

Я видел только пару вопросов, говорящих об этой проблеме, но ни один из них на самом деле не помог

Вот мой код

import time


def time_it(func):  # Here i make a simple decorator function that should time my decorated function
    def wrapper(*args, **kwargs):
        t1 = time.time()
        func(*args)
        t2 = time.time()
        total = t2 - t1
        print("The function '" + func.__name__ + "' took", str(total)[0:5], "seconds to complete")

    return wrapper


@time_it
def square(nums):  # I make a function that squares every number in a list
    new_list = []
    for n in nums:
        new_list.append(n ** 2)
    return new_list


lis = [f for f in range(200000)]  # i make a list with a range of 200000
print(square(lis))  

извините за любые грамматические ошибки, я не являюсь носителем английского языка

Ответы [ 3 ]

3 голосов
/ 07 апреля 2019

Декоратор заменяет square на wrapper, а wrapper ничего не возвращает. Он должен вернуть значение, возвращаемое упакованной функцией.

Это правильный способ сделать это:

def time_it(func):
    def wrapper(*args, **kwargs):
        t1 = time.time()
        try:
            return func(*args, **kwargs)
        finally:
            t2 = time.time()
            total = t2 - t1
            print("The function '" + func.__name__ + "' took", str(total)[0:5], "seconds to complete")

    return wrapper

Я изменил 3 вещи:

  • добавлено return, так что значение возвращается из оформленной функции
  • добавлено **kwargs к func вызовам, потому что это может понадобиться, если используется по-другому
  • добавлен блок try / finally, так что распечатка происходит даже в случае исключения, плюс это облегчает возврат значения.
3 голосов
/ 07 апреля 2019

Проблема в том, что возвращаемое значение вашей внутренней функции не возвращается.Изменение отмечено ниже:

from functools import wraps

def time_it(func):  # Here i make a simple decorator function that should time my decorated function
    @wraps(func)
    def wrapper(*args, **kwargs):
        t1 = time.time()
        ## Note the change on this line -- I now store the return result from the called function 
        result = func(*args, **kwargs)
        t2 = time.time()
        total = t2 - t1
        print("The function '" + func.__name__ + "' took", str(total)[0:5], "seconds to complete")

        ## And then explicitly return the result
        return result

    return wrapper

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

Пара дополнений:

  • from functools import wraps и @wraps(func)
    • , это создаст оберткувнутренняя функция с некоторыми деталями, которые существуют в функции обтекания.Вот небольшой пример в документации по Python: https://docs.python.org/3/library/functools.html
0 голосов
/ 07 апреля 2019

Ваша декорированная функция ничего не возвращает явно - поэтому по умолчанию она возвращает None.

Вы можете захватить вывод перед печатью времени и вернуться в конце:

def time_it(func):  # Here i make a simple decorator function that should time my decorated function
    def wrapper(*args, **kwargs):
        t1 = time.time()
        out = func(*args)
        t2 = time.time()
        total = t2 - t1
        print("The function '" + func.__name__ + "' took", str(total)[0:5], "seconds to complete")
        return out
    return wrapper
...