Reputation: 3495
The general "why global variables are bad" answers don't seem to cover this, so I'm just curious if this would be bad practice or not.
Here is an example of what I mean -
You have one function to generate a list of items
You have another function to build these items
You would like to output the current progress in each function every x seconds, where x is defined at the start of the code.
Would it be bad to set this as a global variable? You'd avoid having to pass an unimportant thing to each function which is what I did in my first code, and it got so messy in some places I had to categorise everything into lists, then pull them out again inside the function. This made it impossible to test individual functions as they needed too much input to run.
Also, if a function only needs one variable to run, I don't want to add anything else to it, so passing a huge list/dictionary containing everything isn't really ideal.
Or alternatively, would it be worthwile setting up a global dictionary to contain any values you may want to use throughout the code? You could set the variable name as the key so it's easy to access wherever it's needed.
I'm not so sure about other versions of Python, but in Maya it's all pretty much contained in the same block of code, so there's no real danger of it affecting anything else.
Upvotes: 0
Views: 254
Reputation: 11
As stated by Daniel, using a global variable isn't bad in itself; however, using them just because it solves the problem doesn't make it a good use of a global variable.
In your example above, you noted you had three conditions: 1) You want a function to generate a list of items 2) You have a second function to build those items (the assumed is that it's being called from the first function) 3) You want to be able to check those items.
None of those indicates a need for a global, but a class may solve your problem. I would suggest using a class similar to the one I have below:
from threading import Thread # To thread the build logic
import random # For random numbers to increase entrophy
import time
class builder( object ):
def __init__(self, numObjs):
self.myList = []
self.numObjs = int(numObjs)
self.inProcess = False
# Build a list of objects
def build(self):
if self.currStatus(False) and self.inProcess == False:
self.inProcess = True
self.currGenThread = Thread(target=self.generate)
self.currGenThread.start()
else:
print "Failed to start new thread -- current thread in process!"
# Generates the objects for the list
def generate(self):
import random, time # Note: Solves thread "not defined" issues
self.myList = []
for currObj in range(self.numObjs):
self.myList.append(currObj)
time.sleep(random.randint(0,1)) # Sleep randomly
# Prints the current status
# Return False indicates completion
def currStatus(self, alsoPrint=True):
retVal = True
if len(self.myList) >= self.numObjs:
if self.currGenThread:
self.currGenThread.join()
self.inProcess = False
retVal = False
# Print status if called for
if alsoPrint:
print "Progress %d -- %s" % (len(self.myList)/self.numObjs,
str(self.myList))
return retVal
obj = builder(10)
obj.build()
while obj.currStatus():
time.sleep(1)
It's not the perfect example, but if you run that code you get something like this:
$python test.py
Progress 0 -- []
Progress 0 -- [0, 1, 2, 3]
Progress 0 -- [0, 1, 2, 3, 4]
Progress 0 -- [0, 1, 2, 3, 4, 5]
Progress 0 -- [0, 1, 2, 3, 4, 5, 6]
Progress 0 -- [0, 1, 2, 3, 4, 5, 6, 7, 8]
Progress 1 -- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
python test.py
Progress 0 -- []
Progress 0 -- [0, 1]
Progress 0 -- [0, 1, 2, 3, 4, 5, 6, 7]
Progress 1 -- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
You can do the same thing with a global or in several other ways. Hopefully this helps.
Upvotes: 1
Reputation: 77377
Global is great if you really want just one set of data. And modifying globals has reasonable use cases also. Take the re
module for example. It caches regular expressions its already seen in a global dict to save the cost of recompiling. Although re
doesn't protect its cache with a lock, its common to use threading.Lock
to make sure you don't insert the same key multiple times.
Upvotes: 0
Reputation: 1323
Maybe your design with function is bad. Consider using class to do this thinfs. Read about design patterns like Builder, Decorator, iterator etc.
Upvotes: 0
Reputation: 599866
Global variables aren't bad in themselves. What's bad is modifying global variables in your functions. Reading global constants, which is what you're proposing here, is fine - you don't even need the global
keyword, since Python will look up the var in surrounding scopes until it finds it. You might want to put your variable in ALL_CAPS to signify that it is indeed a constant.
However, you still might consider whether your code would be better structured as a class, with your variable as an instance attribute.
Upvotes: 2