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
Related
I am writing a recursive function to make permutations of digits from 0 to n. The program will return the th permutation that is obtained. It all works well but I had to use the cheap trick of defining count as a list, that is count=[0]. In this way I am using the properties of lists in order to properly update the variable count[0] at each iteration.
Ideally, what I would like to do is to define count as an integer number instead. However, this does not work because count is then updated only locally, within the scope of the function at the time it is called.
What is the proper way to count the iterations in a recursive function like this?
Below I show the code. It works, but I hate the way I am using count here.
import numpy as np
N=10
available=np.ones(N)
def permutations(array, count=[0], n=N, start=0, end=N, th=100):
if count[0]<th:
for i in range(n):
if available[i]:
array[start]=i
if end-start>1:
available[i]=0
permutations(array, count, n, start+1, end)
available[i]=1
else:
count[0]+=1
break
if count[0]==th:
a=''.join(str(i) for i in array)
return a
def main():
array=[0 for _ in range(N)]
count=[0]
print(permutations(array, count, N, start=0, end=N))
if __name__=="__main__":
main()
Not necessarily ideal but to answer the question, one could use a global variable as follows:
import numpy as np
N = 10
available = np.ones(N)
count = 0
def permutations(array, n=N, start=0, end=N, th=100):
global count
if count < th:
for i in range(n):
if available[i]:
array[start] = i
if end-start > 1:
available[i] = 0
permutations(array, n, start+1, end)
available[i] = 1
else:
count += 1
break
if count == th:
return ''.join(str(i) for i in array)
def main():
array = [0 for _ in range(N)]
print(permutations(array, N, start=0, end=N))
print(f'{count=}')
if __name__ == "__main__":
main()
Output:
0123495786
count=100
Different ways to update a variable from other scopes... and each with its own advantages and disadvantages (performance, access to the variable, ...):
with global approach (as Pingu did),
with nonlocal
and with function's attribute.
The example under consideration, the factorial function, is merely illustrative but it can be easily readapted to your case.
def fact_global(n):
global counter
counter += 1
if n == 1:
return 1
return n*fact_global(n-1)
def fact_nonlocal(n):
counter = 0
def __fact(n):
nonlocal counter
counter += 1
if n == 1:
return 1
return n*__fact(n-1)
return __fact(n)
def fact_attr(n):
fact_attr.counter = 0
def __fact(n):
fact_attr.counter += 1
if n == 1:
return 1
return n*__fact(n-1)
return __fact(n)
n = 10
# case: global
counter = 0
fact_global(n)
print('global', counter)
# case: nonlocal
fact_nonlocal(n)
import inspect
fr = inspect.currentframe()
print('nonlocal', fr.f_locals['counter']) # not recommended, just for curiosity!
# case: function's attribute
fact_attr(n)
print('attr', fact_attr.counter)
Retrieving the value of the variable under investigation is quite straightforward with a global-setting and with function's attribute but not trivial (and not recommended) with nonlocal (inspect is more a debugging tool).
Here a partial result of the workbench:
n=860
fact_nonlocal(n): 2.60644 ± 0.00586
fact_global(n): 2.74698 ± 0.02283
fact_attr(n): 3.01219 ± 0.00539
The results are of the same order of magnitude (due to limitations of the host only tested with a maximum of n=860 so not reliable for an asymptotic conclusion), in this case it seems that it doesn't really matter which one you choose but it is more important to focus on how you are going to access to the variable later in the program.
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)
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
I need to create a message counter object -not to be confused with Python's Counter class. The specification calls for a counter that is initialized to 0, then increments by 1 until it hits 4294967295, at which point it's supposed to cycle back over to 1.
I've implemented a class to do this, but this is just the naive approach. Is there a better way to achieve this goal ?
class MessageCounter():
def __init__(self):
self.value = 0
def increment(self):
if self.value < 4294967295:
self.value += 1
else:
self.reset()
def reset():
self.value = 1
As an alternative to OO, you could create a generating function that yields numbers in sequence, forever. There are a number of ways to do this. In descending order of size and straightforwardness:
def count_loop(upper_limit):
while True:
for i in range(upper_limit):
yield i
gen = count_loop(4294967295)
import itertools
gen = (i for _ in itertools.count() for i in range(4294967295))
gen = (i for _ in iter(int,1) for i in range(4294967295))
You would then retrieve your values by doing next(gen).
>>> next(gen)
0
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
3
(note: Python 2.7 users should use xrange instead of range. However, this may only work for max values smaller than 2^31)
Instead of the reset you can just use the modulo operator:. It will "reset" to 0 instead of one, but that shouldn't matter since you initilized as 0.
def increment(self):
self.value = (value + 1) % 4294967296
I have an example, just more shorter.
class MessageCounter():
def __init__(self):
self.value = 0
def increment(self, reset=False):
self.value = self.value + 1 if self.value < 4294967295 and not reset else 1
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)