San Jose State University Department of Applied Data Science
**DATA 200 Computational Programming for Data Analytics**
Spring 2023 Instructor: Ron Mak
"
]
},
{
"cell_type": "markdown",
"id": "4286f4e5-4839-4d43-9909-2e6f7c3e8b13",
"metadata": {},
"source": [
"## Global vs. Local Variables"
]
},
{
"cell_type": "markdown",
"id": "d7fa787d-0f27-4415-bf3d-ea739e148dd8",
"metadata": {},
"source": [
"#### _TL;DR:_ Just read **The Bottom Line** at the end of all this!"
]
},
{
"cell_type": "markdown",
"id": "d2a73f60-8a10-46a9-8883-ba0d94680f75",
"metadata": {},
"source": [
"#### Variable `x` is **global**."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e808e4fd-435e-44b5-b37c-2abb793e32a1",
"metadata": {},
"outputs": [],
"source": [
"x = 3"
]
},
{
"cell_type": "markdown",
"id": "d3678e6d-ddba-4348-a7b1-9bcd72e86501",
"metadata": {},
"source": [
"#### Function `my_func_1()` below demonstrates that a function can access a global variable such as `x` as long as it doesn't try to modify it. The `id()` function shows that it's been the same variable all along."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "26803e7f-84a3-4b85-b129-6f56b08583c3",
"metadata": {},
"outputs": [],
"source": [
"def my_func_1():\n",
" print(f'{\"In my_func1:\":>25} {id(x) = } {x = }')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ae5bf4b0-befd-4ca0-bbea-72fc9fd593c5",
"metadata": {},
"outputs": [],
"source": [
"print(f'{\"In main before the call:\":>25} {id(x) = } {x = }')\n",
"my_func_1()\n",
"print(f'{\"In main after the call:\":>25} {id(x) = } {x = }')"
]
},
{
"cell_type": "markdown",
"id": "0fcf2545-0863-483c-bbe7-a665749e09cc",
"metadata": {},
"source": [
"#### Function `my_func_2` below modifies variable `x` and therefore, it silently creates a **local** variable `x` that overrides the global variable `x`. The `id()` function confirms that the local `x` is a different variable from the global `x`. After the return to the main, the value of the global `x` is unchanged."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c26fd9dd-95ec-4b49-8de5-b2d97b1a681d",
"metadata": {},
"outputs": [],
"source": [
"def my_func_2():\n",
" x = 7\n",
" print(f'{\"In my_func1:\":>25} {id(x) = } {x = }')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2c13c8a9-98f7-45bc-8841-6e8dc4281efe",
"metadata": {},
"outputs": [],
"source": [
"print(f'{\"In main before the call:\":>25} {id(x) = } {x = }')\n",
"my_func_2()\n",
"print(f'{\"In main after the call:\":>25} {id(x) = } {x = }')"
]
},
{
"cell_type": "markdown",
"id": "fc8fad4a-ec7d-4a93-b6d6-890713c1e06c",
"metadata": {},
"source": [
"#### _Oops!_ Function `my_func3` below fails with an error. It tries to modify global variable `x` and so it must create a local variable `x`. However, `x += 7` is equivalent the `x = x + 7` and so the `x` on the right side of the assignment is the local `x` which doesn't yet have a value (it's \"unbound\")."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c7746ed8-620d-4e51-b4cf-edfdf52ea55f",
"metadata": {},
"outputs": [],
"source": [
"def my_func_3():\n",
" x += 7\n",
" print(f'{\"In my_func1:\":>25} {id(x) = } {x = }')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "978ae10c-1052-466e-8513-8f9f682bc4b3",
"metadata": {},
"outputs": [],
"source": [
"print(f'{\"In main before the call:\":>25} {id(x) = } {x = }')\n",
"my_func_3()\n",
"print(f'{\"In main after the call:\":>25} {id(x) = } {x = }')"
]
},
{
"cell_type": "markdown",
"id": "28970e76-c069-4ce5-9bc6-ea7138b4048f",
"metadata": {},
"source": [
"## Function Parameters"
]
},
{
"cell_type": "markdown",
"id": "7c7b1e38-f7be-4527-8be7-cb46d293cc41",
"metadata": {},
"source": [
"#### Function `my_parm_1()` below confirms that its parameter `p` is a **reference** to the global variable `x` and therefore, parameter `p` is the same variable as `x`. Of course, `x` is unchanged after returning from the call."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a3e3586b-c8b4-45cd-a620-fb6b4ff979d3",
"metadata": {},
"outputs": [],
"source": [
"def my_parm_1(p):\n",
" print(f'{\"In my_parm_1:\":>30} {id(p) = } {p = }')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "07dacef8-1d8a-459e-81c6-809f3a372fe6",
"metadata": {},
"outputs": [],
"source": [
"print(f'{\"In main before the call:\":>30} {id(x) = } {x = }')\n",
"my_parm_1(x)\n",
"print(f'{\"In main after the call:\":>30} {id(x) = } {x = }')"
]
},
{
"cell_type": "markdown",
"id": "a80b3d2b-1850-4c76-81b1-c4a44ce5c1d7",
"metadata": {},
"source": [
"#### Function `my_parm_2()` below modifies its parameter `p`. But before doing so, `p` starts out as a reference to global variable `x`. The statement `p += 7` modifies `p`. Therefore, the function silently creates a new local variable `p`, as confirmed by `id(p)`, and continues executing without an unbound error. After returning from the call, global variable `x` is unchanged."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "10cf5100-29b0-4692-adbc-a400c43eab07",
"metadata": {},
"outputs": [],
"source": [
"def my_parm_2(p):\n",
" print(f'{\"In my_parm_2 before modifying p:\":>35} {id(p) = } {p = }')\n",
" p += 7\n",
" print(f'{\"In my_parm_2 after modifying p:\":>35} {id(p) = } {p = }')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ea12e076-026e-4217-9777-808531e130bc",
"metadata": {},
"outputs": [],
"source": [
"print(f'{\"In main before the call:\":>35} {id(x) = } {x = }')\n",
"my_parm_2(x)\n",
"print(f'{\"In main after the call:\":>35} {id(x) = } {x = }')"
]
},
{
"cell_type": "markdown",
"id": "f13d131f-2853-4483-8bf4-9910ed1f4520",
"metadata": {},
"source": [
"## The Bottom Line\n",
"\n",
"#### This is all somewhat confusing and a source of logic errors that are hard to find. Therefore, follow these guidelines to stay out of trouble:\n",
"- A function should not access any global variables, even if they don't modify them. If a function needs to use the value of a global variable, you should pass the variable as an argument when you call the function. Then the function should use the corresponding parameter.\n",
"- A function should not directly modify the value of its parameters. If a function must modify a parameter's value, it should first **explitly** create a local variable and then work with the local variable instead. For example:\n",
"```\n",
"def func(p):\n",
" local_p = p # explicitly create a local variable\n",
" # Now you can work with local_p and\n",
" # modify its value in subsequent statements.\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "5db44871-2daa-43cb-b0cc-89f034b4ebf1",
"metadata": {},
"source": [
"#### Later, you'll learn that if you pass a global **list** as an argument to a function, it's OK for the function to directly modify the **contents** of the corresponding list parameter. Doing so **will change** the global list's contents."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1e9ce3cd-18d7-4ba3-8baa-c4493483d62e",
"metadata": {},
"outputs": [],
"source": [
"# Copyright (c) 2023 by Ronald Mak"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}