2015-05-21 4 views
1

У меня есть декоратор, который я хочу увеличить счетчик в любое время, когда функция проходит через декоратор. До сих пор это мой кодPython - количество раз проходит через декоратор

from functools import wraps 
def count_check(function): 
    """Returns number of times any function with this decorator is called 
    """ 
    count = [] 
    @wraps(function) 
    def increase_count(*args, **kwargs): 
     count.append(1) 
     return function(*args, **kwargs), len(count) 

    return increase_count 

Он отлично работает, пока другая функция не проходит через декоратор и рассчитывать равным 0 для этой функции. Как я могу суммировать общее количество раз?

+0

работает для меня. Пожалуйста, покажите код, который действительно вызывает плохое поведение. –

+0

Здравствуйте, нет ошибки, просто неожиданного поведения. Например, если я украшаю две функции с помощью @count_check, они оба имеют свой собственный счет, а не суммируют все счета. – Ladmerc

+0

Вам понадобится глобальная переменная счетчика, если вы хотите, чтобы общее количество всех вызовов функции было украшено с помощью @count_check. – junnytony

ответ

1

Это следует сделать это:

from functools import wraps 
def count_check(function, count=[0]): 
    """Returns number of times any function with this decorator is called 
    """ 
    @wraps(function) 
    def increase_count(*args, **kwargs): 
     count[0] += 1 
     return function(*args, **kwargs), count[0] 

    return increase_count 

Вы также можете получить фантазии и использовать словарь подсчета функции по отдельности, а также отдельно:

from functools import wraps 
def count_check(function, count={}): 
    """Returns number of times any function with this decorator is called 
    """ 
    count[function] = 0 
    @wraps(function) 
    def increase_count(*args, **kwargs): 
     count[function] += 1 
     return function(*args, **kwargs), count[function], sum(count.values()) 

    return increase_count 

Демо:

@count_check 
def foo(): 
    return 42 

print(foo(), foo(), foo()) 

@count_check 
def bar(): 
    return 23 

print(bar(), bar(), bar()) 
print(foo(), foo(), foo()) 

Отпечатки:

(42, 1, 1) (42, 2, 2) (42, 3, 3) 
(23, 1, 4) (23, 2, 5) (23, 3, 6) 
(42, 4, 7) (42, 5, 8) (42, 6, 9) 
+0

Спасибо, Стефан, только то, что мне нужно. – Ladmerc

+0

Просто узнал что-то новое .. Не понял, что python оценил аргументы по умолчанию только один раз и поэтому каждый раз возвращает те же самые изменяемые объекты. Мне это нравится. – junnytony

+0

Я сам удивлен. Не знал, что – Ladmerc

0

Я хотел бы попробовать что-то вроде:

from functools import wraps 
count = 0 
def count_check(function): 
    @wraps(function) 
    def increase_count(*args, **kwargs): 
     global count 
     count += 1 
     return function(*args, **kwargs), count 

    return increase_count 
+0

Спасибо junnytony, это сделал трюк. Однако, разве вы не думаете, что это плохая идея ссылаться на счет во всем мире? – Ladmerc

+0

Вообще-то я стараюсь держаться подальше от использования глобальных переменных, но если все count_check делает, это подсчет, сколько раз все функции, обернутые с ним, вызываются, тогда это нормально, так как вы не отслеживаете отдельные вызовы функций. – junnytony