0

I keep getting a syntax error when using += in python here is my code. I am also having troule with nonlocal. I am getting lots of errors including syntax errors and unbound local error Thanks in advance!!!

update: more code added this is all the code It now says local variable 'citizens' referenced before assignment

from time import sleep as slp
import time
import sys
def clear():
  print("\033[2J\033[H", end="")
def slow(text, endl="\n"): 
    for c in text:
        sys.stdout.write(c)
        sys.stdout.flush()
        time.sleep(0.05)
    print(endl, end="")
def slow_in(prompt=''):
    slow(prompt, endl="")
    return input()

import random
def generate():
  import random
  slow("generating random circumstance...")
  slp(2)
  slow("done")


rd = random.randint
money = rd(1, 100)
health = 100
global citizens
citizens = rd(10000, 1000000)
supporters = rd(1,1000000)
def show():
  print("money-" + str(money))
  print("health-" + str(health))
  print("citizens-" + str(citizens))
  print("suppporters-" + str(supporters))

waysod = [""]

def death():
  wod = random.choice(waysod)
  rnum = rd(1,citizens//2)
  citizens -= rnum
  print(str(rnum) + " citizens died " + wod)
  return citizens











import random
rd = random.randint
slow("Welcome to presidential nightmare! ")
from time import sleep as slp
slp(.6)
slow("The easiest thing to do in this game is, well...")
slp(.8)
slow("destroy the country!!")
slp(.6)
slow("lets get started!!!")
slp(.6)
slow_in("press enter to continue...")
generate()
show()
death()

joeisme1
  • 35
  • 5
  • 2
    Remove the `nonlocal` keyword, you are not using it properly and it is not needed here. https://stackoverflow.com/questions/1261875/python-nonlocal-statement – Cory Kramer May 06 '20 at 16:13
  • 1
    nonlocal is only valid inside a nested scope, and must be on its own line. – Aaron May 06 '20 at 16:14
  • Your death() function needs to take a parameter. The easiest way to think about this is that each function is a house, you can't talk to people outside your house while you are inside your house so you need to bring them inside. So in your case you need to do def death(citizens): # Put code in here Also it's better to ask follow up questions in comments or a new post on stack overflow because the answer I posted no longer makes sense with this code. – Kieran Wood May 06 '20 at 23:30

2 Answers2

3

Three things with this code:

  1. the rnum assignment will fail because you are not doing integer division
  2. You actually want global not non-local in this case. Though you should avoid using global variables like this.
  3. You can do the second line as part of the first

This would be what I think you want:

from random import randint as rd
citizens = rd(10000, 1000000)
def function():
  global citizens  # Tells python you want the global value
  rnum = rd(1,citizens//2) # Uses the global value since python knows to do that
  citizens -= rnum   

Though I would recommend avoiding nonlocal altogether since it can cause many bugs down the road. I would suggest doing something like this stylistically:

from random import randint as rd
citizens = rd(10000, 1000000) # Initialize citizens to a random value

def reduce_citizens(citizens:int) -> int:
    """Reduces the number of citizens by up to half of the current amount"""
    rnum = rd(1,citizens//2)
    citizens -= rnum   # Since the value is being passed into the function directly we don't need global
    return citizens # give the new value back so it can be used

citizens = reduce_citizens(citizens) # Take the current value of citizens and remove some then reassign to citizens

The above code has the benefit of being usable with multiple sets of citizens, so for example:

from random import randint as rd
citizens = rd(10000, 1000000)   # Initialize citizens to a random value
citizens_2 = rd(10000, 1000000) # Initialize a second set of citizens to a random value
citizens_3 = rd(10000, 1000000) # Initialize a third set of citizens to a random value

def reduce_citizens(citizens:int) -> int:
    """Reduces the number of citizens by up to half of the current amount"""
    rnum = rd(1,citizens//2)
    citizens -= rnum
    return citizens

citizens = reduce_citizens(citizens) # Take the current value of citizens and remove some then reassign to citizens
citizens_2 = reduce_citizens(citizens) # Take the current value of citizens_2 and remove some then reassign to citizens
citizens_3 = reduce_citizens(citizens) # Take the current value of citizens_3 and remove some then reassign to citizens

Here is a good article and a good video on how scope works in python, but a good rule of thumb is to just keep everything you can local.

Kieran Wood
  • 1,297
  • 8
  • 15
  • I posted the code wrong. I do need the nonlocal keyword now – joeisme1 May 06 '20 at 16:40
  • Do you mind posting the rest of the code, typically nonlocal can (and should) be avoided by using different variable names or better forms of state management. The only real exception being decorator functions. – Kieran Wood May 06 '20 at 16:50
0

The problem is that nonlocal citizens must be on a separate line. Try this:

import random
rd = random.randint
citizens = rd(10000, 1000000)
def function():
   rnum = rd(1,citizens/2)
   nonlocal citizens
   citizens -= rnum
joeisme1
  • 35
  • 5
Krishnan Shankar
  • 780
  • 9
  • 29