Есть ли способ отслеживать количество раз, когда функция вызывается?
Итак, я пытаюсь создать функцию, которая отслеживает, сколько раз вызывается метод.
например:
a = [1,2,3,4]
a.pop()
Я хочу знать, сколько раз a.pop() был вызван до сих пор так для этого примера, я бы получил 1.
Есть ли способ сделать это?
Ответы
Ответ 1
Это не работает для встроенных функций, но интересный подход:
def myfunction():
myfunction.counter += 1
myfunction.counter = 0
Вы предоставляете функции атрибуту, поэтому каждый вызов этого атрибута обновляется. Глобальные переменные не нужны.
Встроенные модули доступны только для чтения. Они не могут быть изменены.
Ответ 2
Вы можете использовать декоратор, который отслеживает, сколько раз функция вызывается. Поскольку list
является встроенным, вы не можете украсить или заменить его метод pop
, поэтому вам придется использовать собственный класс списка, например.
def counted(f):
def wrapped(*args, **kwargs):
wrapped.calls += 1
return f(*args, **kwargs)
wrapped.calls = 0
return wrapped
class MyList(list):
@counted
def pop(self, *args, **kwargs):
return list.pop(self, *args, **kwargs)
x = MyList([1, 2, 3, 4, 5])
for i in range(3):
x.pop()
print x.pop.calls # prints 3
Ответ 3
Я использовал следующий небольшой трюк, чтобы отслеживать, сколько раз функция вызывалась
def myfun(s,i=[0]):
print(s)
i[0]+=1 # mutable variable get evaluated ONCE
return i[0]
>>> myfun('aaa')
aaa
1
>>> myfun('bbb')
bbb
2
Ответ 4
Для пинков я написал ответ, используя декоратор:
class counter:
#wraps a function, to keep a running count of how many
#times it been called
def __init__(self, func):
self.func = func
self.count = count
def __call__(self, *args, **kwargs):
self.count += 1
return self.func(*args, **kwargs)
Чтобы использовать его, просто украсьте функцию. Затем вы можете проверить, сколько раз эта функция была запущена путем изучения атрибута "count". Делать это так хорошо, потому что:
1.) Нет глобальных переменных. Счет напрямую связан с функцией.
2.) Вы можете легко скомпилировать встроенные функции, вызвав класс напрямую:
sum_wrapped = counter(sum)
sum_wrapped([1, 2 ,3, 4])
#outputs 10
print sum_wrapped.count
#outputs 1
Конечно, это можно было бы улучшить, используя модуль Decorators, чтобы сохранить docstrings и другие хорошие вещи неповрежденными. Кроме того, для отличного обзора того, что декораторы и как они работают, ознакомьтесь с fooobar.com/questions/329/....
Ответ 5
Один из подходов - создать прокси экземпляра, для которого вы хотите подсчитать доступ к атрибуту:
from collections import Counter
class CountingProxy():
def __init__(self, instance):
self._instance = instance
self.count = Counter()
def __getattr__(self, key):
if hasattr(self._instance, key):
self.count[key] += 1
return getattr(self._instance, key)
>>> l = [1,2,3,4,5]
>>> cl = CountingProxy(l)
>>> cl.pop()
5
>>> cl.append(10)
>>> cl.index(3)
2
>>> cl.reverse()
>>> cl.reverse()
>>> cl.count
Counter({'reverse': 2, 'pop': 1, 'append': 1, 'index': 1})
Ответ 6
Простой способ сделать это - увеличить глобальную переменную каждый раз, когда вы вызываете функцию.
counter = 0
a = [1,2,3,4]
a.pop()
counter += 1
Ответ 7
counter = 0
def pop():
counter += 1
print counter
#other function code
a = [1,2,3,4]
a.pop()
это должно решить вашу проблему, и вы должны уметь видеть, что подсчитывается. +
каждый раз, когда вы вызываете функцию, счетчик увеличивается и печатается с каждым проходом функции.
ЕСЛИ ЕГО ВСТРОЕН В:
counter = 0
def newfunction():
a = [1,2,3,4]
a.pop()
counter += 1
print counter
логика в этом состоит в том, что она вызовет вашу новую функцию, войдя в функцию, которая будет готова, затем выйдет из встроенной функции, а затем продолжит отмечать счетчик как увеличенный. выведите свой счетчик.
Ответ 8
Вот простое и элегантное решение для функции самосчета без каких-либо декораторов, глобальных переменных и т.д.:
def hello():
hello.counter += 1
print(hello.counter)
hello.counter = 0
Каждый раз, когда вы звоните hello()
, он печатает 1
, 2
и т.д.
Давайте не будем забывать, что в Python функция является первоклассным гражданином и на это есть права. И один из них должен иметь атрибуты!
Если вы хотите включить вызов метода в функцию, это может быть легко:
def pop_counted(a):
pop_counted.counter += 1
return a.pop()
pop_counted.counter = 0
Вуаля!
Комментарий
Это работает, потому что функция Python "знает" себя (это необходимая функция, поэтому функции могут вызывать себя рекурсивно, если это необходимо).
Если вы хотите сохранить некоторую информацию о функции, возможно, лучше хранить ее там, где она должна быть: в атрибуте функции.
Преимущество не в использовании глобальной переменной - это область действия:
- нет риска конфликта имен в глобальном пространстве имен
- информация, которую вы хранили, исчезнет, как только функция будет удалена из стека, а это именно то, что вам нужно - мусора не останется.
Бонусом является то, что этот подход будет работать в тех случаях, когда глобальная переменная не очень подходит, как правило, для вложенных функций, где вы не можете объявить "глобальный" во внешней функции.
Ответ 9
Просто определите глобальный оператор в своей функции.
count = 1
def your_func():
global count
print(count)
count= count +1
Ответ 10
Просто определите глобальную переменную и увеличьте ее внутри функции.
a = 0
def some_function():
global a
a+=1
<..Your code.>
Это будет автоматически увеличиваться при использовании функции, и вы можете получить к ней глобальный доступ.