Related
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 have written a function to calculate the heading between two points only if a vehicle reports that it's moving and that the vehicle has moved 20cm between points.
The function uses static variables - or at least it would if it worked - to keep track of previous positions and heading values.
Here is the code:
def withCan(pos):
eastdist = pos[0]-previous_pos[0]
northdist = pos[1]-previous_pos[1]
canflag = pos[2]
if (canflag == 1 or canflag==2):
if (previous_canflag == 1 and canflag == 2):
previous_heading += 180.0
previous_canflag = canflag
elif (previous_canflag == 2 and canflag == 1):
previous_heading += 180.0
previous_canflag = canflag
else:
previous_canflag = canflag
if ( (canflag == 1 or canflag == 2) and math.sqrt(northdist*northdist+eastdist*eastdist) > canstep ):
previous_heading = math.degrees(math.atan2(eastdist, northdist))
previous_pos[0] = pos[0]
previous_pos[1] = pos[1]
return previous_heading
withCan.previous_pos = [0.0,0.0]
withCan.previous_heading = 0.0
withCan.previous_canflag = 0
withCan.canstep = 0.2
positions = backandforth([100,100]) #populates an array of form [x,y,canflag]
for p in positions:
print withCan(p)
I am getting an error that says eastdist = pos[0]-previous_pos[0]
NameError: global name 'previous_pos' is not defined. Please could someone explain the cause of this error?
When you do this:
def foo():
pass
foo.name = 1
You are not creating a global name name. Instead you are adding a property to the foo function! You can access it with:
def foo():
return foo.name
foo.name = 1
But that is quite weird. If you need a global name, just do it:
def foo():
global name
name += 1
return name
name = 1
Remember that if you want to modify the global name from the function, you have to declare it as global. If you fail to do this, you can use it but you cannot assign to it.
Your confusion with static names may come from using classes. But note that in your code withCan is not a class, it is a plain function!
It looks like what you are trying to do is writing a class...
class WithCan():
def __init(self, previous_pos)__:
self.previous_pos=previous_pos
def withCan(self, pos):
# your function as class method
Then you could initialize an instance
withCan=WithCan(previous_pos)
and access it
withCan.previous_pos=...
You can do static variables in Python using function attributes, but you need to use the full name inside the function to access those attributes.
Here's a short demo.
def test(a):
print a, a + test.b
test.b += 1
test.b = 5
test(3)
test(10)
output
3 8
10 16
However, it would be more usual to do this sort of thing using a class, as shown in Tim's answer.
Another way to do statics in Python is to give your function default mutable arguments, but many people are uncomfortable with that. But if you're curious, please see “Least Astonishment” in Python: The Mutable Default Argument.
Let me contribute a perhaps more streamlined way of emulating static variables in functions that could make the OP's example maybe easier to read:
def with_can(pos):
if not hasattr(with_can, "canflag"):
# set up and initialise the static variables
with_can.canflag = 0
with_can.previous_pos = [0.0,0.0]
with_can.previous_heading = 0.0
with_can.canstep = 0.2
# ... use them ...
eastdist = pos[0]-with_can.previous_pos[0]
# ... etc ...
Basically at the first invocation we detect that one of the "static" variables (canflag) is not yet there so we add and initialise all of them. After that they can be used as indicated.
However, as others have pointed out already, it is much better to write a class with data members instead of these "static" function variables.
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)
I'm new to python and am trying to create a program to test some methods of object creation. Currently, I'm writing a program that involves creating objects, giving them a unique numeric variable, and assigning them to a list for future referencing. Here's what I wrote to create the variable names:
def getRectangleName():
rectName = list("Rectangle")
SPAWNEDOBJECTLIST.append(len(SPAWNEDOBJECTLIST))
rectName.append(str(len(SPAWNEDOBJECTLIST)))
return rectName
and then that's passed onto something to turn that string into a variable name. I tried eval(), learned this was Bad for some reason and it didn't work anyway, and tried some workarounds to no avail.
I figure there's plenty of games that have an indefinite number of characters on the screen. Is there an established way of making iterations of objects like this?
The objects themselves have an X and Y so that they act as reference points for the display of rectangles on screen(the idea in the future is to have each one move around on their own, so simply making lists of X and Y to draw rectangles isn't useful).
Edit: The problem is that I don't know how to give each object its own variable to put it on a list for future referencing.
Edit2: I don't think I'm asking the right question, actually, or using the right terminology. I need to be able to have an indefinite number of objects created on the fly after the program is already running, and be able to reference them individually.
The problem is that I don't know how to give each object its own variable to put it on a list for future referencing.
Whenever you think you need variables you didn't type into your program, you're doing something wrong. You don't need to assign something to a variable to put it on a list:
x = [1, 2, 3] # Note how I don't assign 1, 2, or 3 to variables.
x.append(4) # 4 doesn't get a variable either.
x.append(make_a_rectangle()) # We create a rectangle and stick it on the list.
do_stuff_with(x[4]) # We pass the rectangle to a function.
x = [] # New list.
for i in xrange(n):
x.append(make_a_rectangle()) # This happens n times.
# At this point, we have n rectangles, none of them associated with their own
# variable, none of them with a name.
If you think you need names for things (and quite often, you don't really need the names), you can use a dict:
x = {}
x['foo'] = make_a_rectangle()
do_stuff_with(x['foo'])
It's not a great idea to combine the function of managing the rectangles -- accessing, adding, or deleting them -- with the idea of being rectangles. You never know when you might need to maintain multiple lists, or change from unordered lists to organized ones.
Until you really need more, keep the management functions simple: use built-in lists or dictionaries. Use lists if you just care about ordering, or only need to know you have a bunch of stuff:
class Rectangle (object):
def __init__(self, top, bottom, left, right):
self.Top = top
self.Left = left
self.Right = right
self.Bottom = bottom
list_of_rects = [Rectangle(10,0,0,10), Rectangle(20, 10, 10 ,20)]
# how many rects?
len(list_of_rects)
# result: 2
# where is this particular rect?
fred = Rectangle(30,20,20, 30)
list_of_rects.insert(fred, 1)
list_of_rects.index(fred)
# result: 1
#remove an item from the list:
list_of_rects.remove(fred)
#search the list:
right_of_5 = [rect for rect in list_of_rects if rect.Left > 5]
If you need to get access to the individual rects for some reason -- 'what's the rectangle of the goal' or something -- you have two choices:
1) the code that needs the rect just keeps a reference to it:
class Goal(object):
def __init__(self, rect):
self.Rect = rect
goalrect = Rectangle (0,0,20,20)
mygoal = Goal(goalrect)
list_of_rects.append(goalrect)
# now goalrect always knows about it's own rect, but the list can keep track of it too...
2) Or, use a dictionary:
named_rects = {}
named_rects['goal'] = Rectangle(0,0,20,20)
You get all the same abilities with a dictionary that you do with a list -- add, delete, and find -- except dictionaries don't preserve order, so you can't manage things like priority:
# add to the dict:
named_rects['new_rect'] = Rectangle(90,90,95,95)
# remove
del named_rects['new_rect']
# find = is there a known key?
if 'new_rect' in named_rects: print new_rect
# search:
right_of_5 = [rect for rect in named_rects.items() if rect.Left > 5]
There are cases where you need fancier things than plain old lists and dicts -- but always try it with the free stuff first :)
If you dynamically want to create variables and add them to class instances, use this
class MainClass:
def __setattr__(self, name, value):
self.__dict__[name] = value
def getRectangleNameGenerator(N = 10):
X = 0
while X <= N:
X += 1
yield "Rectangle" + str(X)
RectangleName = getRectangleNameGenerator()
ClassInstances = {next(RectangleName) : MainClass}
ClassInstances[next(RectangleName)] = MainClass
ClassInstances["Rectangle1"].Temp = 10
print ClassInstances["Rectangle1"].Temp
If the class is going to have only X and Y,
class MainClass:
X, Y = 0, 0
def getRectangleNameGenerator(N = 10):
X = 0
while X <= N:
X += 1
yield "Rectangle" + str(X)
RectangleName = getRectangleNameGenerator()
ClassInstances = {next(RectangleName) : MainClass}
ClassInstances[next(RectangleName)] = MainClass
ClassInstances["Rectangle1"].X = 11
print ClassInstances["Rectangle1"].X
If you really want to refer to your rectangle instances by name, I would suggest to keep a dictionary at class level. Something like this:
#! /usr/bin/python3
from threading import Lock
import random
class Rectangle:
instances = {}
lock = Lock ()
#classmethod
def forName (cls, name):
return cls.instances [name] if name in cls.instances else None
#classmethod
def push (cls, inst):
with cls.lock:
name = None
while not name or name in cls.instances:
name = ''.join (random.choice ('abcdefghij') for i in range (16) )
cls.instances [name] = inst
return name
def __init__ (self):
self.name = Rectangle.push (self)
names = [Rectangle ().name for i in range (5) ]
for name in names:
print (name, Rectangle.forName (name) )
I need to increment a variable each time a certain number of calls to a certain function is made in Python 2.7.3.
For example, feetTraveled = 0. for every 12 calls to travelOneInch(), feetTraveled += 1.
Is it optimal to use a for loop or should I be using something different?
If it is optimal to use a for loop like the one above, what should be placed instead of 'every 12 calls to'?
Another example: I have four servants. They each do one task in a clock tick, and the time counter is initially time = 0. So for every four calls to servantDo(), time += 1.
In this case, I think I'd use an instance method:
class Foo(object):
def __init__(self):
self.inches = 0
self.feet = 0
def travel_one_inch(self):
self.inches += 1
if self.inches > 11:
self.inches = 0
self.feet += 1
def __str__(self):
return "{feet} feet and {inches} inches".format(feet=self.feet,inches=self.inches)
a = Foo()
for _ in range(123):
a.travel_one_inch()
print(a)
A vast majority of the time, if you want a function to remember some sort of state between calls, you're not looking for a function at all -- You're looking for a class with an instance method.
If you want to work in the global namespace:
inches = 0
feet = 0
def travelOneInch(sure):
inches += 1
if (inches % 12) == 0:
feet += 1
#...
And using inches % 12 == 0 is better than inches > 12 in case you want your function to recognize the second and furher feet.
mgilson (above) knows what's up. If I were you, I'd do the following, to make things easier:
class Foo(object):
def __init__(self):
self.__inches = 0
def travel_one_inch(self):
self.__inches += 1
def feetTraveled(self):
return self.__inches // 12
But, in terms of optimality, if you're just doing this once, then you can use temporary variables:
feetTraveled = 0
inchesTraveled = 0
for i in xrange(72):
# as in mgilson's answer
inchesTraveled += 1
if inchesTraveled > 11:
inchesTraveled = 0
feetTraveled += 1
Probably the best implementation is to use an object to store the status and use the function to modify it:
class Position(object):
def __init__(self):
self.pos = 0
def advance(self,inches=1):
self.pos += inches
def pos_as_foot(self):
return self.pos // 12
If you find this approach a little to boring (even if it's the most correct one), you can try a more esoteric approach: you can use internal values of the function, i.e. treating it like an object
def foo():
foo.value+=1
if foo.value and not foo.value%12:
foo.result+=1
foo.value=0
foo.result=0
for i in range(15):
foo()
print foo.value
#15
print foo.result
#1
It's not the most easy solution, and have problem if you need several counters, but it's interesting to know. It has the advantage to remove some cluttering code (at least in simple cases) from the class definition (that is using under the hood), and keep the state accessible whereever you will use the function, without tampering with global variables (that i reaaaly don't like)