{"id":"scope-global","slug":"global","title":"The global keyword","text":"A function can read a global variable. But as soon as a function assigns to a name, that name is a local variable of the function, even when a global variable of the same name exists:\n\n```python\nscore = 0\n\n\ndef add_points(points):\n    score = points\n    print(\"Inside:\", score)\n\n\nadd_points(5)\nprint(\"Outside:\", score)\n```\n\n```output\nInside: 5\nOutside: 0\n```\n\nThe assignment created a new local `score`. The global `score` is still 0.\n\nPython decides this for the whole function before it runs it: a name the function assigns to anywhere in it is local everywhere in it. That's why this function fails, although it looks as if it simply adds to the global variable:\n\n```python\nscore = 0\n\n\ndef add_points(points):\n    score += points\n\n\nadd_points(5)\nprint(score)\n```\n\n```crash\nTraceback (most recent call last):\n  File \"main.py\", line 8, in <module>\n    add_points(5)\n    ~~~~~~~~~~^^^\n  File \"main.py\", line 5, in add_points\n    score += points\n    ^^^^^\nUnboundLocalError: cannot access local variable 'score' where it is not associated with a value\n```\n\n`score += points` is short for `score = score + points`, which is an assignment, so `score` is local in `add_points`. To work out the new value, Python first reads the local `score`, which has no value yet: an **UnboundLocalError**.\n\n### global\n\nThe statement **`global`** at the start of a function says that a name means the global variable. Then assigning to it changes the global variable:\n\n```python\nlives = 3\n\n\ndef lose_life():\n    global lives\n    lives -= 1\n    print(\"Ouch! Lives left:\", lives)\n\n\nlose_life()\nlose_life()\nif lives > 0:\n    print(\"Still in the game\")\n```\n\n```output\nOuch! Lives left: 2\nOuch! Lives left: 1\nStill in the game\n```\n\n`global` is only needed to assign to a global variable. Reading one needs nothing, and neither does changing the contents of a global list with a method such as `append`, because that doesn't assign to the variable.\n\n### When to use it, and when not\n\nUse `global` sparingly. A function that changes global variables can't be understood on its own: to know what it does, you need to know what the rest of the program does to the same variables, and it can't be reused in another program without them. Above all, `global` is not a way to get a result out of a function:\n\n```python\ndef average(numbers):\n    global result\n    result = sum(numbers) / len(numbers)\n```\n\nThis works, but `return sum(numbers) / len(numbers)` is better: the caller decides where the result goes, and the function works the same wherever it's used.\n\nGlobal variables are reasonable for a few things that really belong to the whole program: the state of a game, such as the lives left above, or a counter of how many times something has happened in the program.\n","task":"Fill in the blank so that each call of `press` adds one to the global `count`, and the program prints:\n\n```\nPressed 3 times\n```\n","kind":"fill","seed":"count = 0\n\n\ndef press():\n    [[global]] count\n    count += 1\n\n\npress()\npress()\npress()\nprint(\"Pressed\", count, \"times\")\n","solution":"count = 0\n\n\ndef press():\n    global count\n    count += 1\n\n\npress()\npress()\npress()\nprint(\"Pressed\", count, \"times\")\n","hints":["Without the missing word, `count += 1` would make `count` a local variable and stop with an `UnboundLocalError`.","The keyword that makes `count` mean the global variable is `global`."],"tests":[{"name":"Output","stdin":"","expect":"Pressed 3 times","hidden":false}],"require":[],"forbid":[],"more":[{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"x = 1\n\n\ndef a():\n    x = 2\n    print(x)\n\n\ndef b():\n    global x\n    x = 3\n    print(x)\n\n\na()\nprint(x)\nb()\nprint(x)\n","solution":"x = 1\n\n\ndef a():\n    x = 2\n    print(x)\n\n\ndef b():\n    global x\n    x = 3\n    print(x)\n\n\na()\nprint(x)\nb()\nprint(x)\n","hints":["`a` assigns to `x` without `global`, so it creates a local `x`. The global `x` stays 1.","`b` says `global x`, so its assignment changes the global `x` to 3."],"tests":[{"name":"Output","stdin":"","expect":"2\n1\n3\n3","hidden":false}],"require":[],"forbid":[],"lines":["2","1","3","3"]},{"task":"A ticket machine gives out numbers in order. Write a function `next_ticket()` that returns the next ticket number: one more than the global variable `last_ticket`, which the function also updates. With `last_ticket` at 0, the first call returns 1, the next 2, and so on.\n\nFor example, with the starter code's `last_ticket = 0`, three calls print:\n\n```\n1\n2\n3\n```\n","kind":"code","seed":"last_ticket = 0\n\n\ndef next_ticket():\n    pass\n\n\nif __name__ == \"__main__\":\n    print(next_ticket())\n    print(next_ticket())\n    print(next_ticket())\n","solution":"last_ticket = 0\n\n\ndef next_ticket():\n    global last_ticket\n    last_ticket += 1\n    return last_ticket\n\n\nif __name__ == \"__main__\":\n    print(next_ticket())\n    print(next_ticket())\n    print(next_ticket())\n","hints":["The function assigns to `last_ticket`, so it needs `global last_ticket` as its first line.","Add one to `last_ticket` and return its new value."],"tests":[{"name":"Test 1","stdin":"","call":"print(next_ticket())\nprint(next_ticket())\nprint(next_ticket())\n","expect":"1\n2\n3","hidden":false},{"name":"Test 2","stdin":"","call":"last_ticket = 41\nprint(next_ticket())\nprint(next_ticket())\n","expect":"42\n43","hidden":true},{"name":"next_ticket()","stdin":"","call":"next_ticket()\n","expect":"1","hidden":true,"returns":true}],"require":[{"pattern":"\\bglobal\\s+last_ticket\\b","message":"Use `global last_ticket` so the function can update the global counter."}],"forbid":[]}]}