0

I want to count the number of calls of the function f inside of inc. How should I modify the function main to do it?

I have this code:

def inc(f):
    f()
    f()

def main():
    a = 0
    def f():
        a += 1
    inc(f)
    print(a)  # should print 2

main()

But it leads to the error:

Traceback (most recent call last):
  File "main.py", line 11, in <module>
    main()
  File "main.py", line 9, in main
    inc(f)
  File "main.py", line 2, in inc
    f()
  File "main.py", line 8, in f
    a += 1
UnboundLocalError: local variable 'a' referenced before assignment
Fomalhaut
  • 8,590
  • 8
  • 51
  • 95

4 Answers4

7

The usual way is to create an attribute func.invocations for your function func, like

def func(a):
    func.invocations += 1
    return a + 1

func.invocations = 0

and use it like

func(1)    # 2
func(10)   # 11
func.invocations  # 2

To make the whole thing more reusable and readable you can also create a decorator counter that allows you to count the number of calls on any function you like:

import functools

def counter(fn):
    @functools.wraps(fn)
    def helper(*args, **kargs):
        helper.invocations += 1
        return fn(*args, **kargs)
    helper.invocations = 0
    return helper

and then use it like

@counter
def func(a):
    return a + 1

func(1)    # 2
func(10)   # 11
func.invocations # 2
Nils Werner
  • 34,832
  • 7
  • 76
  • 98
1
def inc(f):
    f()
    f()

def main():
    a = 0
    def f():
        nonlocal a
        a += 1
    inc(f)
    print(a)  # should print 2

main()

Make a nonlocal in f()

Negi Babu
  • 507
  • 4
  • 11
  • this is overly complicated for no reason. Take a look at my answer. – Ma0 Jun 14 '18 at 11:49
  • 1
    Please do not advise to use `global` when a `nonlocal` would be enough. Or at least edit your answer to explain that `nonlocal` could be used here. – Serge Ballesta Jun 14 '18 at 11:52
  • @SergeBallesta Thankyou.I have made the changes. Can you please state the difference between what I did earlier and now? – Negi Babu Jun 14 '18 at 11:56
  • 1
    @NegiBabu: it doen't change much in that code. But in a larger script a global is directly accessible to the whole program while a nonlocal is still constraint in the enclosing block. Making something global is generally or good immediate solution that later makes evolutions harder. Best practices recommend to avoid it if you can. – Serge Ballesta Jun 14 '18 at 12:02
  • Using nonlocal or global variables is not a nice solution that may turn around and bite you if your code gets more complicated than this simple example. – Nils Werner Jun 15 '18 at 08:56
0

If you are looking for a simple solution, a global variable would do the trick.

reps = 0

def f():
    global reps 
    reps  += 1
    # do your func stuff here

f()
f()
f()
f()  # called f() 4 times
print(reps)  # -> 4
Ma0
  • 15,057
  • 4
  • 35
  • 65
0

You try this:

def inc(f):    
    f()    
    f() 


def main():    
    a = 0     
    def f():     
        f.counter += 1    
    f.counter =0    
    inc(f)     
    print(f.counter) 


main()

How functions are objects in python you can create an attribute to count the number of call to that function

Ma0
  • 15,057
  • 4
  • 35
  • 65
juancarlos
  • 593
  • 3
  • 9