Подтвердить что ты не робот

Есть ли способ отслеживать количество раз, когда функция вызывается?

Итак, я пытаюсь создать функцию, которая отслеживает, сколько раз вызывается метод. например:

a = [1,2,3,4]
a.pop()

Я хочу знать, сколько раз a.pop() был вызван до сих пор так для этого примера, я бы получил 1. Есть ли способ сделать это?

4b9b3361

Ответ 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.>

Это будет автоматически увеличиваться при использовании функции, и вы можете получить к ней глобальный доступ.