I get the following error:
Warning (from warnings module):
File "C:\Python34\projectEuler\projectEuler.py", line 316
global primeSet, primeList, primeCap, primeRan
SyntaxWarning: name 'primeRan' is used prior to global declaration
For the code:
primeSet = {2, 3}
primeList = [2, 3]
primeCap = 3
primeRan = False
def primeGen():
if primeRan:
primeList, primeCap = primeList, PrimeCap
global primeSet
else:
global primeSet, primeList, primeCap, primeRan
primeRan = True
for i in primeList:
yield i
while(True):
primeCap += 2
m = int(primeCap**.5)
yesPrime = True
for p in primeList:
if p > m: break
if primeCap%p == 0:
yesPrime = False
break
if yesPrime:
primeSet.add(primeCap)
primeList.append(primeCap)
yield primeCap
The variable is not written until it is assigned. And the code seems to work. Is the syntax message a false alarm, or should a global be declared before being read? (instead of only declaring before being written)
The code:
def primeGen():
global primeRan
if primeRan:
primeList, primeMax = primeList, PrimeCap
global primeSet
else:
global primeSet, primeList, primeCap
primeRan = True
Gets rid of the SyntaxWarning
. But it seems wrong to make the global deceleration for a value that is only being read and not written.
Should I ignore the syntax alarm?
No, you can't ignore it and, as of Python 3.6
this will cease to be a SyntaxWarning
and instead be updated to an error (SyntaxError
). So you better fix it now or face it the prospect of it not executing in future versions (>= 3.6
) .
See the docs on the global
statement:
Names listed in a
global
statement must not be used in the same code block textually preceding that global statement.
As you noticed, this isn't a warning that is generated at run-time, it is generated when Python compiles your function object and notices a global
statement containing a name (primeRan
) that has already been found as local.
You should add the global
statement before referencing primeRan
here and also do the same for primeList
which falls victim to the same issue.
For primeList
, though, you can be sneaky and take advantage of the fact that global
must be parsed first. In short, switch the condition over so Python parses the global
statement for it before the assignment statement:
def primeGen():
global primeRan
if not primeRan:
global primeSet, primeList, primeCap
primeRan = True
else:
primeList, primeMax = primeList, PrimeCap
# rest as is
Since global
is a directive for the parser, this yields the same behavior w/o the warning.
Of course, using globals
is not a good practice. I can't see any reason why you'd require using them to be honest, you're always better off (and from a conceptual point of view and execution speed wise) to drop the usage of globals
and instead communicate with your function using arguments and return values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With