This question already has answers here:
Are global variables thread-safe in Flask? How do I share data between requests?
(4 answers)
Closed 4 years ago.
I am trying to update a Python function's name incrementally based on the number of times it has been called.
An example of the original function can be seen below:
def function():
function.counter += 1
return print('call 0')
function.counter = 0
Below is the function I would like to be generated the second time the above function is called:
def function1():
function.counter1 += 1
return print ('call 1')
And so on with each previous function call resulting in the creation of a new function which adds 1 to the previous function's name. Once function1() is called, function2() would be created, then once function 2() is called function3() would be created, and so on. Is there a straightforward way I could go about this?
You should not declare multiple functions like that, there are better ways to accomplish what you want.
Generators
Using generators is well suited for your specific example.
def count(start=0):
while True:
yield start
start += 1
g1 = count()
next(g1) # 0
next(g1) # 1
g10 = count(10)
next(g10) # 10
itertools module
The previous example is already implemented by itertools.count.
from itertools import count
g1 = count()
next(g1) # 0
next(g1) # 1
g10 = count(10)
next(g10) # 10
Closure
If you want a function with some state, use a closure instead of function attributes.
def count(start=0):
_state = {'count': start - 1}
def inner():
_state['count'] += 1
return _state['count']
return inner
f1 = count()
f1() # 0
f1() # 1
This can be ideal approach to solve this problem,instead of creating multiple functions for each increment.Use a class and store the counter as variable and call the corresponding method to increment and get_count
class CouterExample(object):
"""Sample DocString:
Attributes:
counter: A integer tracking the current counter.
"""
def __init__(self, counter=0):
"""Return a CounterExample object with counter."""
self.counter = counter
def increment(self, amount):
"""Sets the counter after increment."""
if amount > 1:
self.counter += amount
def get_counter(self):
"""Return the counter value."""
return self.counter
Related
I'm wondering if there's a way to have member variables in a function instance. For example,
incr_instance = incrementor(1)
incr_instance()
incr_instance()
incr_instance()
would print out
1
2
3
Yes, I know I can just use a class, but this is a question about weird language quirks in the python language.
You can have a function incrementor that returns another function that keeps incrementing the counter n (the inner function uses nonlocal n to access n instead of using incrementor.n):
def incrementor(n):
def inc():
nonlocal n
n += 1
return n - 1
return inc
Test:
incr_instance = incrementor(1)
incr_instance_2 = incrementor(10)
print(incr_instance())
print(incr_instance())
print(incr_instance())
print(incr_instance_2())
print(incr_instance_2())
print(incr_instance_2())
print(incr_instance())
print(incr_instance())
print(incr_instance())
print(incr_instance_2())
print(incr_instance_2())
print(incr_instance_2())
Output:
1
2
3
10
11
12
4
5
6
13
14
15
You can do the following:
def incrementor(n):
def incrementor_aux():
incrementor_aux.x += n
print(incrementor_aux.x)
incrementor_aux.x = 0
return incrementor_aux
You can even create multiple incrementors and have them increment their values independantly:
incr_instance1 = incrementor(1)
incr_instance2 = incrementor(1)
incr_instance1() #prints 1
incr_instance1() #prints 2
incr_instance2() #prints 1
incr_instance1() #prints 3
incr_instance2() #prints 2
What happens is a new instance of incrementor_aux function is created everytime you call incrementor, with its own x local value which stays in each instance's scope.
Here's one that doesn't use function attributes:
from functools import partial
def increment(x):
def gen():
y = x
while True:
y += 1
yield y
g = gen()
return partial(next, g)
f1 = increment(1)
f1()
# 2
f1()
# 3
f2 = increment(0)
f2()
# 1
f2()
# 2
f1()
# 4
def incrementor(i=0):
def inc():
inc.i += 1
return inc.i
inc.i = i - 1
return inc
incr_inst = incrementor(1)
incr_inst() # 1
incr_inst() # 2
But for this actual task
from itertools import count
incr = count(1)
incr() # 1
incr() # 2
Looks like you want a factory that gives you functions with local state, without using a class. Instead of making the state variable a member of the function, I'd use python's nonlocal syntax:
def incrementor(start):
state = start -1
def interior():
nonlocal state
state += 1
return state
return interior
This will print 7, then 8:
inc7 = incrementor(7)
print(inc7())
print(inc7())
This will print 1, then 9 10, then 2 3; each of the functions inc1() and inc7() is going at its own pace.
inc1 = incrementor(1)
print(inc1())
# Yes, I can mix them
print("inc7 again:", inc7(), inc7())
print("inc1 again:", inc1(), inc1())
I fancied having a go at this and tried to make it concise, here's what I ended up with. It's not best practice but you asked for quirky!
The aim here was to not pass the value back into the function, as the OP requested.
index = 0;
incr_instance = lambda: [index, exec("global index; index += 1")]
print(incr_instance()[0])
print(incr_instance()[0])
print(incr_instance()[0])
Will print
0
1
2
Index is our global which keeps track of our progress, the lambda expression executes two statements. The first statement returns the value of index and the second increments it, which had to be done using exec as you cannot assign variables from a lambda as it's for expressions only. The two statements are within square brackets in order to run both; otherwise it will return index only.
The [0] index gives us the value of index rather than the result of the exec expression (always None)
I am reading the following tutorial about Python decorators tutorial. Everything is more or less clear except the following code:
def call_counter(func):
def helper(x):
helper.calls += 1
return func(x)
helper.calls = 0
return helper
#call_counter
def succ(x):
return x + 1
print(succ.calls)
for i in range(10):
succ(i)
print(succ.calls)
I cannot fully understand helper.calls notation. Is is just variable with no relations to helper function? Also how does succ function gets access to calls?
In Python functions are objects, that means you can set variables too.
def func():
pass
func.count = 0
print(func.count) # 0
func.count += 1
print(func.count) # 1
We can rewrite the decoration to this:
def succ(x):
return x + 1
succ = call_counter(succ)
So now you have a decorated succ. As you can see in call_counter, it actually returns a function called helper. And this helper function has one attribute named calls which is used to count calls. So now when you call succ(i), you are actually calling that helper function.
And yes that calls is just a normal variable.
I am needing a function that will increment by one every time it is called. I have used count but every time I do it resets the count back to the original value plus one count. I have seen lots of code but none of it works. Here is what I have now
I have done lots of looking into loops and iterations
def count_row():
count = 1
while count >= 1:
yield count
count += 1
return count
You can use itertools.count.
from itertools import count
counter = count(1)
next(counter) # 1
next(counter) # 2
Stateful function
If you absolutely want a stateful function instead of calling next, you can wrap the count in a function.
def counter(_count=count(1)):
return next(_count)
counter() # 1
counter() # 2
Class
Alternatively, itertools.count being a class, you can inherit from it to extend it's behaviour and make it a callable.
class CallableCount(count):
def __call__(self):
return next(self)
counter = CallableCount(1)
counter() # 1
counter() # 2
Using a class would be my preferred approach since it allows instantiating multiple counters.
You need a closure. Define a function make_counter which initializes a local variable, then defines and returns a function that increments that variable on each call.
def make_counter():
count = -1
def _():
count += 1
return count
return _
count_row = make_counter()
Now count_row will return a new value on each call:
>>> count_row()
0
>>> count_row()
1
This is sort of the dual of a class. You have a function that "wraps" some data (closes over the variable), instead of a piece of data with an associated method. The class version; note the similarity to make_counter:
class Count:
def __init__(self):
self.count = -1
def __call__(self):
self.count += 1
return count
An instance of this class now behaves like our previous closure.
>>> count_row = Count()
>>> count_row()
0
>>> count_row()
1
You can use a generator here that increments value by one every time it's called using next():
def count_row():
count = 0
while True:
count += 1
yield count
itr = count_row()
print(next(itr)) # 1
print(next(itr)) # 2
If you look closely, this is equivalent to what itertools.count() does.
if I got this right this should work:
count=0
def count_row(count):
count += 1
return count
I'm refreshing my memory about some python features that I didn't get yet, I'm learning from this python tutorial and there's an example that I don't fully understand. It's about a decorator counting calls to a function, here's the code:
def call_counter(func):
def helper(x):
helper.calls += 1
return func(x)
helper.calls = 0
return helper
#call_counter
def succ(x):
return x + 1
if __name__ == '__main__':
print(succ.calls)
for i in range(10):
print(succ(i))
print(succ.calls)
What I don't get here is why do we increment the calls of the function wrapper (helper.calls += 1) instead of the function calls itself, and why does it actually working?
The important thing to remember about decorators is that a decorator is a function that takes a function as an argument, and returns yet another function. The returned value - yet another function - is what will be called when the name of the original function is invoked.
This model can be very simple:
def my_decorator(fn):
print("Decorator was called")
return fn
In this case, the returned function is the same as the passed-in function. But that's usually not what you do. Usually, you return either a completely different function, or you return a function that somehow chains or wraps the original function.
In your example, which is a very common model, you have an inner function that is returned:
def helper(x):
helper.calls += 1
return func(x)
This inner function calls the original function (return func(x)) but it also increments the calls counter.
This inner function is being inserted as a "replacement" for whatever function is being decorated. So when your module foo.succ() function is looked up, the result is a reference to the inner helper function returned by the decorator. That function increments the call counter and then calls the originally-defined succ function.
When you decorate a function you "substitute" you're function with the wrapper.
In this example, after the decoration, when you call succ you are actually calling helper. So if you are counting calls you have to increase the helper calls.
You can check that once you decorate a function the name is binded tho the wrapper by checking the attribute _name_ of the decorated function:
def call_counter(func):
def helper(*args, **kwargs):
helper.calls += 1
print(helper.calls)
return func(*args, **kwargs)
helper.calls = 0
return helper
#call_counter
def succ(x):
return x + 1
succ(0)
>>> 1
succ(1)
>>> 2
print(succ.__name__)
>>> 'helper'
print(succ.calls)
>>> 2
Example with Class Decorator
When you decorate a function with the Class Decorator, every function has its own call_count. This is simplicity of OOP. Every time CallCountDecorator object is called, it will increase its own call_count attribute and print it.
class CallCountDecorator:
"""
A decorator that will count and print how many times the decorated function was called
"""
def __init__(self, inline_func):
self.call_count = 0
self.inline_func = inline_func
def __call__(self, *args, **kwargs):
self.call_count += 1
self._print_call_count()
return self.inline_func(*args, **kwargs)
def _print_call_count(self):
print(f"The {self.inline_func.__name__} called {self.call_count} times")
#CallCountDecorator
def function():
pass
#CallCountDecorator
def function2(a, b):
pass
if __name__ == "__main__":
function()
function2(1, b=2)
function()
function2(a=2, b=3)
function2(0, 1)
# OUTPUT
# --------------
# The function called 1 times
# The function2 called 1 times
# The function called 2 times
# The function2 called 2 times
# The function2 called 3 times
What I don't get here is why do we increment the calls of the function wrapper (helper.calls += 1) instead of the function calls itself, and why does it actually working?
I think to make it a generically useful decorator. You could do this
def succ(x):
succ.calls += 1
return x + 1
if __name__ == '__main__':
succ.calls = 0
print(succ.calls)
for i in range(10):
print(succ(i))
print(succ.calls)
which works just fine, but you would need to put the .calls +=1 in every function you wanted to apply this too, and initialise to 0 before you ran any of them. If you had a whole bunch of functions you wanted to count this is definitely nicer. Plus it initialises them to 0 at definition, which is nice.
As i understand it it works because it replaces the function succ with the helper function from within the decorator (which is redefined every time it decorates a function) so succ = helper and succ.calls = helper.calls. (although of course the name helper is only definied within the namespace of the decorator)
Does that make sense?
As I understand this (correct me if I'm wrong) the order you program executes is:
Register call_function.
Register succ.
While registering succ function interpreter finds a decorator so it executes call_function.
Your function returns an object which is a function (helper). And adds to this object field calls.
Now your function succ has been assigned to helper. So when you call your function, you're actually calling helper function, wrapped within a decorator. So every field you add to your helper function is accessible outside by addressing succ because those 2 variables refer to same thing.
So when you call succ() it's basically the same if you would do helper(*args, **argv)
Check this out:
def helper(x):
helper.calls += 1
return 2
helper.calls = 0
def call_counter(func):
return helper
#call_counter
def succ(x):
return x + 1
if __name__ == '__main__':
print(succ == helper) # prints true.
So i'm trying to make a function that keeps track how many times a method is called.
for example:
a = [1,2,3,4]
a.pop()
i want to know how many times a.pop() was called so far so for this example, i would get 1.
Is there a way to do this?
This doesn't work for builtin functions, but an interesting approach would be:
def myfunction():
myfunction.counter += 1
myfunction.counter = 0
You're giving the function an attribute, so every call that attribute is updated. No global variables needed.
Built-ins are read-only. They cannot be modified.
You could use a decorator that tracks how many times the function is called. Since list is a built-in, you can't decorate or replace its pop method so you'd have to use your own list class, for example.
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
i used the following little trick to track how many times the function was called
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
Here is a simple and elegant solution for a self counting function, without any decorators, global variables, etc:
def hello():
hello.counter += 1
print(hello.counter)
hello.counter = 0
Each time you call hello(), it will print 1, 2, etc.
Let's not forget that, in Python, a function is a first-class citizen
and it has rights. And one of them is to have attributes!
If you are willing to include your method call in a function, it can be easy:
def pop_counted(a):
pop_counted.counter += 1
return a.pop()
pop_counted.counter = 0
VoilĂ !
Comment
This works because a Python function "knows" itself (this is a necessary feature, so that functions can call themselves recursively if desired).
If you wish to keep some information about a function, it might be better to keep it where it belongs: in an attribute of the function.
The advantage of not using a global variable is scope:
no risk of name collisions in the global namespace
the information you were keeping will vanish as soon as the function is taken off the stack, which is what you want -- no garbage left.
A bonus is that this approach will work in cases where a global variable is not really a good option, typically for nested functions where you can't declare a "global" in the outer function.
For kicks, I wrote up an answer using a decorator:
class counter:
#wraps a function, to keep a running count of how many
#times it's 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)
To use it, simply decorate a function. You can then check how many times that function has been run by examining the "count" attribute. Doing it this way is nice because:
1.) No global variables. The count is associated directly with the function.
2.) You can wrap builtin functions easily, by calling the class directly:
sum_wrapped = counter(sum)
sum_wrapped([1, 2 ,3, 4])
#outputs 10
print sum_wrapped.count
#outputs 1
Of course, this could be improved by using the Decorators module to keep the docstrings and other good things intact. Also, for an excellent overview of what decorators are, and how they work, check out this stackoverflow answer.
One approach is to create a proxy of the instance for which you want to count attribute access:
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})
A simple way to do this is to increment a global variable each time you call the function.
counter = 0
a = [1,2,3,4]
a.pop()
counter += 1
i guess the following code will be helpful to you. you just need to make local variable global in order to access the global variable from a method
MYGLOBAL = 5
def func1():
global MYGLOBAL
MYGLOBAL +=10
def func2():
print (MYGLOBAL)
func1() #called the func1 three time thus the value of MYGLOBAL WILL increase 10*3=30
func1() #called the func1 three time thus the value of MYGLOBAL WILL increase 10*3=30
func1() #called the func1 three time thus the value of MYGLOBAL WILL increase 10*3=30
func2() #this will printout 5+30=35
counter = 0
def pop():
counter += 1
print counter
#other function code
a = [1,2,3,4]
a.pop()
this should solve your issue and you should be able to see whats being counted. +
every time you call the function the counter is going to be increased and printed with every pass of the function.
IF ITS BUILT IN:
counter = 0
def newfunction():
a = [1,2,3,4]
a.pop()
counter += 1
print counter
the logic in this is that it will call your new function go into the function that is premade then step out of the built in function and then go on to mark the counter as increased. the output your counter.
Just define a global statement in your function.
count = 1
def your_func():
global count
print(count)
count= count +1
Just define a global variable and increment it inside function.
a = 0
def some_function():
global a
a+=1
<..Your code.>
This will automatically be incremented as function is used and you can access it globally.
I did it copying the way JavaScript console.count() method works. That's my code:
class Terminal(object):
__count_names = []
def count(self, name='default'):
# check if name already exists
i = next((self.__count_names.index(item) for item in self.__count_names if item['name'] == name), None)
# if name argument does not exist register it
if i is None:
dictionary = { 'name': name, 'count': 1 }
self.__count_names.append(dictionary)
# if exists increment 'count'
else:
dictionary = self.__count_names[i]
dictionary['count'] += 1
self.__count_names[i] = dictionary
# finally print name and count
print(f"{dictionary['name']} : {dictionary['count']}")
Your code should look like this:
terminal = Terminal()
def myFunc():
terminal.count("myFunc")
myFunc()
myFunc()
myFunc("myFunc")
Output:
myFunc: 1
myFunc: 2
myFunc: 3
myFunc: 4
An example from Datacamp, using decorators:
def counter(func):
def wrapper(*args, **kwargs):
wrapper.count += 1
# Call the function being decorated and return the result
return func(*args, **kwargs)
wrapper.count = 0
# Return the new decorated function
return wrapper
# Decorate foo() with the counter() decorator
#counter
def foo():
print('calling foo()')
foo()
foo()
print('foo() was called {} times.'.format(foo.count))
# output
calling foo()
calling foo()
foo() was called 2 times.
I solve this with closure. This is a generic function:
def counter(fn):
cnt=0
def inner(*args,**kwargs):
nonlocal cnt
cnt+=1
print('{0} has been called {1} times'.format(fn.__name__,cnt))
return fn(*args,**kwargs)
return inner
a=[1,2,3,4]
a_pop=counter(a.pop)