Итак, я пытаюсь создать функцию, которая отслеживает, сколько раз вызывается метод. например:
a = [1,2,3,4]
a.pop()
Я хочу знать, сколько раз a.pop() был вызван до сих пор так для этого примера, я бы получил 1. Есть ли способ сделать это?
Итак, я пытаюсь создать функцию, которая отслеживает, сколько раз вызывается метод. например:
a = [1,2,3,4]
a.pop()
Я хочу знать, сколько раз a.pop() был вызван до сих пор так для этого примера, я бы получил 1. Есть ли способ сделать это?
Это не работает для встроенных функций, но интересный подход:
def myfunction():
myfunction.counter += 1
myfunction.counter = 0
Вы предоставляете функции атрибуту, поэтому каждый вызов этого атрибута обновляется. Глобальные переменные не нужны.
Встроенные модули доступны только для чтения. Они не могут быть изменены.
Вы можете использовать декоратор, который отслеживает, сколько раз функция вызывается. Поскольку 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
Я использовал следующий небольшой трюк, чтобы отслеживать, сколько раз функция вызывалась
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
Для пинков я написал ответ, используя декоратор:
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/....
Один из подходов - создать прокси экземпляра, для которого вы хотите подсчитать доступ к атрибуту:
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})
Простой способ сделать это - увеличить глобальную переменную каждый раз, когда вы вызываете функцию.
counter = 0
a = [1,2,3,4]
a.pop()
counter += 1
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
логика в этом состоит в том, что она вызовет вашу новую функцию, войдя в функцию, которая будет готова, затем выйдет из встроенной функции, а затем продолжит отмечать счетчик как увеличенный. выведите свой счетчик.
Вот простое и элегантное решение для функции самосчета без каких-либо декораторов, глобальных переменных и т.д.:
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 "знает" себя (это необходимая функция, поэтому функции могут вызывать себя рекурсивно, если это необходимо).
Если вы хотите сохранить некоторую информацию о функции, возможно, лучше хранить ее там, где она должна быть: в атрибуте функции.
Преимущество не в использовании глобальной переменной - это область действия:
Бонусом является то, что этот подход будет работать в тех случаях, когда глобальная переменная не очень подходит, как правило, для вложенных функций, где вы не можете объявить "глобальный" во внешней функции.
Просто определите глобальный оператор в своей функции.
count = 1
def your_func():
global count
print(count)
count= count +1
Просто определите глобальную переменную и увеличьте ее внутри функции.
a = 0
def some_function():
global a
a+=1
<..Your code.>
Это будет автоматически увеличиваться при использовании функции, и вы можете получить к ней глобальный доступ.