{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [], "authorship_tag": "ABX9TyNI9kwMRrPdqT3WfHMohKDb", "include_colab_link": true }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "view-in-github", "colab_type": "text" }, "source": [ "\"Open" ] }, { "cell_type": "markdown", "source": [ "# **Python Variables and Literals**\n", "In the previous tutorial you learned about Python comments. Now, let's learn about variables and literals in Python.\n", "\n", "Python Variables\n", "In programming, a variable is a container (storage area) to hold data. For example," ], "metadata": { "id": "_tIxhgPe7vdh" } }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "OXex7Fh-7rnW" }, "outputs": [], "source": [ "number = 10" ] }, { "cell_type": "markdown", "source": [ "# **Assigning values to Variables in Python**\n", "As we can see from the above example, we use the assignment operator = to assign a value to a variable.\n", "\n" ], "metadata": { "id": "hibaSL_87yha" } }, { "cell_type": "code", "source": [ "# assign value to site_name variable\n", "site_name = 'programiz.pro'\n", "\n", "print(site_name)\n", "\n", "# Output: programiz.pro" ], "metadata": { "id": "AnnIYuI37ynR" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Python Literals**\n", "Literals are representations of fixed values in a program. They can be numbers, characters, or strings, etc. For example, 'Hello, World!', 12, 23.0, 'C', etc.\n", "\n" ], "metadata": { "id": "Dn9i0FKj7yuZ" } }, { "cell_type": "code", "source": [ "site_name = 'programiz.com'" ], "metadata": { "id": "cH58XfQI7yzh" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Python Numeric Literals**\n", "Numeric Literals are immutable (unchangeable). Numeric literals can belong to 3 different numerical types: Integer, Float, and Complex.\n", "\n", "1. Integer Literals\n", "Integer literals are numbers without decimal parts. It also consists of negative numbers. For example, 5, -11, 0, 12, etc.\n", "\n", "2. Floating-Point Literals\n", "Floating-point literals are numbers that contain decimal parts.\n", "\n", "Just like integers, floating-point numbers can also be both positive and negative. For example, 2.5, 6.76, 0.0, -9.45, etc.\n", "\n", "3. Complex Literals\n", "Complex literals are numbers that represent complex numbers.\n", "\n", "Here, numerals are in the form a + bj, where a is real and b is imaginary. For example, 6+9j, 2+3j.\n", "\n", "Python String Literals\n", "\n", "Python Boolean Literals\n", "\n", "Character Literals in Python\n", "\n", "Special Literal in Python\n", "\n", "Collection Literals\n", "\n" ], "metadata": { "id": "rJqUo_5O7y5R" } }, { "cell_type": "code", "source": [ "# list literal\n", "fruits = [\"apple\", \"mango\", \"orange\"]\n", "print(fruits)\n", "\n", "# tuple literal\n", "numbers = (1, 2, 3)\n", "print(numbers)\n", "\n", "# dictionary literal\n", "alphabets = {'a':'apple', 'b':'ball', 'c':'cat'}\n", "print(alphabets)\n", "\n", "# set literal\n", "vowels = {'a', 'e', 'i' , 'o', 'u'}\n", "print(vowels)" ], "metadata": { "id": "cSCWPw5Z7y_J" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Python Variables - Assign Multiple Values**\n", "Many Values to Multiple Variables\n", "Python allows you to assign values to multiple variables in one line:" ], "metadata": { "id": "H2wTsF-z7zEx" } }, { "cell_type": "code", "source": [ "x, y, z = \"Orange\", \"Banana\", \"Cherry\"\n", "print(x)\n", "print(y)\n", "print(z)" ], "metadata": { "id": "vdynZT7B7zKq" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **One Value to Multiple Variables**\n", "And you can assign the same value to multiple variables in one line:" ], "metadata": { "id": "V5rBqDuO7zQp" } }, { "cell_type": "code", "source": [ "x = y = z = \"Orange\"\n", "print(x)\n", "print(y)\n", "print(z)" ], "metadata": { "id": "N-hQ3TUt7zWR" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Unpack a Collection**\n", "If you have a collection of values in a list, tuple etc. Python allows you to extract the values into variables. This is called unpacking.\n", "\n" ], "metadata": { "id": "wWv6pPGB7zcx" } }, { "cell_type": "code", "source": [ "fruits = [\"apple\", \"banana\", \"cherry\"]\n", "x, y, z = fruits\n", "print(x)\n", "print(y)\n", "print(z)" ], "metadata": { "id": "fTyK6tjg7ziB" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Output Variables**\n", "The print() function is often used to output variables." ], "metadata": { "id": "BDTtKPToCt9w" } }, { "cell_type": "code", "source": [ "x = \"Python is awesome\"\n", "print(x)" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Lx7SElppCuGA", "outputId": "6b074446-0391-49e2-974a-65bed1cd9af9" }, "execution_count": 1, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Python is awesome\n" ] } ] }, { "cell_type": "markdown", "source": [ "# **Global Variables**\n", "Variables that are created outside of a function (as in all of the examples in the previous pages) are known as global variables." ], "metadata": { "id": "dGZvC5dvCuMQ" } }, { "cell_type": "code", "source": [ "x = \"awesome\"\n", "\n", "def myfunc():\n", " print(\"Python is \" + x)\n", "\n", "myfunc()" ], "metadata": { "id": "1M4DSeoCCuSo" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **The global Keyword**\n", "Normally, when you create a variable inside a function, that variable is local, and can only be used inside that function.\n", "\n", "To create a global variable inside a function, you can use the global keyword." ], "metadata": { "id": "NcHP40csCuaP" } }, { "cell_type": "code", "source": [ "def myfunc():\n", " global x\n", " x = \"fantastic\"\n", "\n", "myfunc()\n", "\n", "print(\"Python is \" + x)" ], "metadata": { "id": "1hHYsznhCuhA" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **What Is a Variable?**\n", "A variable is a name bound to an object. In Python, you create a binding with the assignment operator =. Names are not typed; they can point to any object (string, int, list, function, and so on)." ], "metadata": { "id": "46VicI2eCumw" } }, { "cell_type": "code", "source": [ "customer_name = \"Ava Torres\"\n", "order_count = 1\n", "total_cents = 1 + 2 * 300 # evaluated first, then bound" ], "metadata": { "id": "tJM78dPHCuta" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "Follow these rules and conventions when naming variables to avoid syntax errors and subtle bugs.\n", "\n", "Use letters, digits, and underscores only; names cannot start with a digit.\n", "Do not use keywords such as True, for, or class as names.\n", "Avoid shadowing built-ins like list, dict, sum, or max.\n", "Prefer snake_case for readability (PEP 8)." ], "metadata": { "id": "9rAFhjCtCu0Y" } }, { "cell_type": "code", "source": [ "first string value = \"First string\" # spaces not allowed\n", "# SyntaxError: invalid syntax\n", "\n", "1st_value = 10 # cannot start with a digit\n", "# SyntaxError: invalid decimal literal\n", "\n", "True = \"yes\" # cannot assign to a keyword\n", "# SyntaxError: cannot assign to True" ], "metadata": { "id": "xQurCJ9rCu6g" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **How Python Scope Works (LEGB)**\n", "Scope is the region of code where a name is visible. When you use a name, Python looks it up in this order (LEGB):\n", "\n", "**Local:** the current function’s scope.\n", "Enclosing: any outer function scopes (for nested functions).\n", "**Global: **the module’s top level (module namespace).\n", "**Built-in:** names defined by Python in builtins (for example, len, print).\n", "Names live in namespaces (think dictionaries mapping names to objects). Scope is about which namespaces Python consults to resolve a name at a given point in code.\n", "\n", "**Local scope**\n", "Names assigned inside a function are local to that function unless declared otherwise. They are not visible outside the function." ], "metadata": { "id": "OvnOue6PCvAZ" } }, { "cell_type": "code", "source": [ "def show_order_id():\n", " order_id = 42\n", " print(\"inside function:\", order_id)\n", "\n", "show_order_id()\n", "print(\"outside function:\", order_id) # NameError" ], "metadata": { "id": "z3R70L64CvFp" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Enclosing scope (closures)**\n", "Nested functions can see names from their immediately enclosing function. To rebind such a name (not just read it), declare it nonlocal." ], "metadata": { "id": "NXFa4xe1EvUg" } }, { "cell_type": "code", "source": [ "def make_step_counter():\n", " count = 0 # enclosing scope for 'increment'\n", "\n", " def increment():\n", " nonlocal count # rebind the 'count' in the nearest enclosing function\n", " count += 1\n", " return count\n", "\n", " return increment\n", "\n", "step = make_step_counter()\n", "print(step()) # 1\n", "print(step()) # 2" ], "metadata": { "id": "BCLP5bbBEvbo" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Global scope**\n", "Names assigned at the top level of a module live in the module’s global namespace. Any function can read them. To assign to a module-level name from inside a function, declare it global." ], "metadata": { "id": "AQYlAgW_Evho" } }, { "cell_type": "code", "source": [ "greeting = \"Hello\"\n", "\n", "def greet_city(city_name):\n", " print(greeting, city_name) # reads global\n", "\n", "def set_greeting(new_greeting):\n", " global greeting\n", " greeting = new_greeting # rebinds global\n", "\n", "greet_city(\"Nairobi\") # Hello Nairobi\n", "set_greeting(\"Hi\")\n", "greet_city(\"Nairobi\") # Hi Nairobi" ], "metadata": { "id": "VAFO1WBLEvpQ" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Built-in scope (and a note on keywords)**\n", "The built-in scope contains names like len, print, and Exception. Avoid shadowing them, or you’ll lose access to the built-in for that scope." ], "metadata": { "id": "9ozYyNj4Evvg" } }, { "cell_type": "code", "source": [ "list = [1, 2, 3] # shadows the built-in 'list' constructor\n", "list(\"abc\") # TypeError: 'list' object is not callable\n", "del list # fix by deleting the shadowing name" ], "metadata": { "id": "c8DTEE-pEv3v" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Blocks, Loops, and Comprehensions**\n", "Python’s block statements and comprehensions have specific scoping behaviors that often surprise developers coming from other languages.\n", "\n", "There is no block scope for if/for/while/with\n", "Assignments inside these blocks affect the containing scope (function or module). Loop variables also remain defined after the loop ends." ], "metadata": { "id": "LqBiDkUdEv-P" } }, { "cell_type": "code", "source": [ "if True:\n", " status = \"ready\"\n", "print(status) # \"ready\"\n", "\n", "for i in range(3):\n", " pass\n", "print(i) # 2 (the last value from the loop)" ], "metadata": { "id": "wnaZk0XwEwEw" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Comprehensions isolate their iteration variable**\n", "List, dict, and set comprehensions have their own local scope for loop variables. The iteration variable does not leak into the surrounding scope." ], "metadata": { "id": "fM4T_ewtEwKv" } }, { "cell_type": "code", "source": [ "numbers = [1, 2, 3]\n", "[x for x in numbers]\n", "print(\"x\" in globals() or \"x\" in locals()) # False" ], "metadata": { "id": "LiqNbBMlEwQ5" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Using the global Keyword**\n", "Declare a name as global inside a function when you need to rebind a module-level variable. Place the declaration near the top of the function so it’s obvious which variable you are modifying." ], "metadata": { "id": "rLGgqPU3EwYQ" } }, { "cell_type": "code", "source": [ "tax_rate = 0.08\n", "\n", "def configure_tax(rate):\n", " global tax_rate\n", " tax_rate = float(rate)\n", "\n", "def total_with_tax(cents):\n", " return int(cents * (1 + tax_rate))\n", "\n", "configure_tax(0.10)\n", "print(total_with_tax(1000)) # 1100" ], "metadata": { "id": "MN5kY_LCEwd4" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Using the nonlocal Keyword**\n", "Use nonlocal to rebind a name from the nearest enclosing function scope. This is common in closures that maintain state." ], "metadata": { "id": "ZB0ehxwNEwki" } }, { "cell_type": "code", "source": [ "def make_accumulator(start=0):\n", " total = start\n", " def add(amount):\n", " nonlocal total\n", " total += amount\n", " return total\n", " return add\n", "\n", "acc = make_accumulator()\n", "print(acc(5)) # 5\n", "print(acc(10)) # 15" ], "metadata": { "id": "x-fbfLI9EwqA" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **locals() and globals() in 2025**\n", "These functions are useful for inspection and debugging, not for updating variables. Starting in Python 3.13 (PEP 667), each call to locals() in a function returns an independent snapshot. Editing that snapshot does not change real locals. I confirmed this behavior by running the following snippet on Python 3.13:\n", "\n" ], "metadata": { "id": "Wx6FKR-aFNqE" } }, { "cell_type": "code", "source": [ "def probe():\n", " project = \"alpha\"\n", " snap1 = locals()\n", " snap1[\"project\"] = \"beta\" # edits the snapshot only\n", " observed = project # still \"alpha\"\n", " snap2 = locals() # new snapshot\n", " return snap1[\"project\"], observed, snap2[\"project\"]\n", "\n", "print(probe()) # ('beta', 'alpha', 'alpha')" ], "metadata": { "id": "9Fp7oU-TFNxM" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Common Pitfalls and How to Fix Them**\n", "These mistakes account for most scope-related errors I see in practice.\n", "\n", "UnboundLocalError from assigning in a function: Python treats a name as local if it’s assigned anywhere in the function. Either move the read after the assignment, rename, or add global/nonlocal as appropriate.\n", "Expecting block scope: Names assigned in if/for/while/with persist in the containing scope. Use tighter helper functions to limit scope.\n", "Shadowing built-ins: Avoid names such as list, dict, sum, id, or min. Choose descriptive names like customer_list or min_allowed.\n", "Forgetting nonlocal in closures: If you intend to update an outer function variable, declare it nonlocal. Otherwise you create a new local and the outer value doesn’t change.\n", "Confusing keywords with built-ins: Keywords (syntax) cannot be used as names, ever. Built-ins can be shadowed but shouldn’t be." ], "metadata": { "id": "K5d3Nf11FN3t" } }, { "cell_type": "code", "source": [], "metadata": { "id": "mZ_Py7CyFN-M" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# **Best Practices That Keep Scope Simple**\n", "These habits make code easier to read, test, and debug.\n", "\n", "Favor small, focused functions. Define variables in the narrowest scope that works.\n", "\n", "Pass data in and out via parameters and return values. Minimize module-level state.\n", "\n", "Use closures intentionally. Document which outer names a nested function captures, and use nonlocal when you truly need to rebind.\n", "\n", "Choose descriptive, non-conflicting names. A leading underscore (for example, _cache) signals internal use.\n", "\n", "Treat locals()/globals() as read-only diagnostics, not a configuration mechanism." ], "metadata": { "id": "UFcJDzarFOFV" } } ] }