{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "ULxWGdhVqcRt" }, "source": [ "# Chapter 3: Operators and Expressions\n", "\n", "```{image} abertura-light.png\n", ":alt: Five circles of points filled with chords linking each point to its multiple, forming cardioid patterns\n", ":class: abertura only-light\n", "```\n", "\n", "```{image} abertura-dark.png\n", ":alt: Five circles of points filled with chords linking each point to its multiple, forming cardioid patterns\n", ":class: abertura only-dark\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have already seen how to store information in variables and work with different data types. Now it is time to learn how to **manipulate** that information through operators and expressions.\n", "\n", "**Operators** are special symbols that perform operations on values, such as adding two numbers, comparing strings, or combining logical conditions. **Expressions**, in turn, are combinations of values and operators that produce a result.\n", "\n", "Mastering operators and expressions is essential to:\n", "- Perform mathematical calculations of any complexity\n", "- Make decisions based on conditions\n", "- Validate user input\n", "- Manipulate strings, lists, and other collections\n", "- Write more concise and efficient code\n", "\n", "In this chapter we will see the main operators in Python, organized into categories: arithmetic, relational, logical, ternary, membership, assignment, and bitwise. We will also learn how operators interact with each other through **operator precedence**.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Arithmetic Operators\n", "\n", "Arithmetic operators are the first ones we learn in any programming language because they work much like the math we already know. They let us perform mathematical operations on numbers, whether integers or decimals.\n", "\n", "### Arithmetic Operators Table\n", "\n", "Python provides seven basic arithmetic operators. Let's get to know each one:\n", "\n", "| Operator | Symbol | Description | Example | Result |\n", "|---|---|---|---|---|\n", "| **Addition** | `+` | Adds two values | `3 + 5` | `8` |\n", "| **Subtraction** | `-` | Subtracts the second value from the first | `10 - 3` | `7` |\n", "| **Multiplication** | `*` | Multiplies two values | `4 * 2` | `8` |\n", "| **Division** | `/` | Divides the first value by the second (always returns a decimal) | `10 / 2` | `5.0` |\n", "| **Floor Division** | `//` | Divides and returns only the integer part | `10 // 3` | `3` |\n", "| **Modulo** | `%` | Returns the remainder of the division | `10 % 3` | `1` |\n", "| **Exponentiation** | `**` | Raises the first value to the power of the second | `2 ** 3` | `8` |\n", "\n", "### Understanding Each Operator\n", "\n", "Let's explore some of these operators in more detail:\n", "\n", "**Division (`/`) vs Floor Division (`//`)**\n", "\n", "The difference between `/` and `//` matters:\n", "- The `/` operator always returns a decimal number (float), even when the division is exact\n", "- The `//` operator returns only the integer part, discarding the decimal part\n", "\n", "```python\n", "print(10 / 2)\n", "print(10 // 2)\n", "print(10 / 3)\n", "print(10 // 3)\n", "```\n", "\n", "**Output:**\n", "```\n", "5.0\n", "5\n", "3.3333333333333335\n", "3\n", "```\n", "\n", "The figure below shows the three readings of the same division.\n", "\n", "```{image} divisao-euclidiana-light.png\n", ":alt: Two panels. In the first, ten dots grouped three by three, forming three complete groups and leaving one dot over outside them, with the expression 10 floor divided by 3 equals 3 written under the groups and 10 modulo 3 equals 1 written under the leftover. In the second, the equality 10 equals 3 times 3 plus 1, with the words dividend, divisor, quotient and remainder under the matching terms, and below it the line 10 divided by 3 equals 3.3333\n", ":class: only-light\n", "```\n", "\n", "```{image} divisao-euclidiana-dark.png\n", ":alt: Two panels. In the first, ten dots grouped three by three, forming three complete groups and leaving one dot over outside them, with the expression 10 floor divided by 3 equals 3 written under the groups and 10 modulo 3 equals 1 written under the leftover. In the second, the equality 10 equals 3 times 3 plus 1, with the words dividend, divisor, quotient and remainder under the matching terms, and below it the line 10 divided by 3 equals 3.3333\n", ":class: only-dark\n", "```\n", "\n", "**Modulo Operator (`%`)**\n", "\n", "The modulo operator is very useful in many situations:\n", "- Checking whether a number is even or odd\n", "- Determining whether a number is a multiple of another\n", "- Getting the last digit of a number\n", "- Cyclic operations (such as clocks)\n", "\n", "```python\n", "# Check whether a number is even\n", "number = 8\n", "if number % 2 == 0:\n", " print(f\"{number} is even\")\n", "else:\n", " print(f\"{number} is odd\")\n", "\n", "# Get the last digit of a number\n", "value = 12345\n", "last_digit = value % 10\n", "print(f\"Last digit: {last_digit}\")\n", "```\n", "\n", "**Output:**\n", "```\n", "8 is even\n", "Last digit: 5\n", "```\n", "\n", "**Exponentiation Operator (`**`)**\n", "\n", "The `**` operator replaces functions like `pow()` and makes the code more readable:\n", "\n", "```python\n", "# Compute the area of a circle: A = π * r²\n", "radius = 5\n", "PI = 3.14159\n", "area = PI * radius ** 2\n", "print(f\"Circle area: {area:.2f}\")\n", "```\n", "\n", "**Output:**\n", "```\n", "Circle area: 78.54\n", "```\n", "\n", "### Practical Examples\n", "\n", "Let's see examples that combine several operators in everyday situations:\n", "\n", "**Example 1: Shopping calculator with discount**\n", "\n", "```python\n", "original_price = 150.00\n", "quantity = 3\n", "discount_percent = 10\n", "\n", "# Calculations\n", "subtotal = original_price * quantity\n", "discount = subtotal * (discount_percent / 100)\n", "total = subtotal - discount\n", "\n", "print(f\"Subtotal: $ {subtotal:.2f}\")\n", "print(f\"Discount ({discount_percent}%): $ {discount:.2f}\")\n", "print(f\"Total to pay: $ {total:.2f}\")\n", "```\n", "\n", "**Output:**\n", "```\n", "Subtotal: $ 450.00\n", "Discount (10%): $ 45.00\n", "Total to pay: $ 405.00\n", "```\n", "\n", "**Example 2: Time conversion**\n", "\n", "```python\n", "# Convert total seconds into hours, minutes and seconds\n", "total_seconds = 3725\n", "\n", "hours = total_seconds // 3600 # How many full hours\n", "remainder_after_hours = total_seconds % 3600 # Remaining seconds\n", "minutes = remainder_after_hours // 60 # How many full minutes\n", "seconds = remainder_after_hours % 60 # Remaining seconds\n", "\n", "print(f\"{total_seconds} seconds is equivalent to:\")\n", "print(f\"{hours} hour(s), {minutes} minute(s) and {seconds} second(s)\")\n", "```\n", "\n", "**Output:**\n", "```\n", "3725 seconds is equivalent to:\n", "1 hour(s), 2 minute(s) and 5 second(s)\n", "```\n", "\n", "### Precedence of Arithmetic Operators\n", "\n", "Like in math, Python follows a specific order when evaluating expressions. That order is called **operator precedence**:\n", "\n", "| Priority | Operators | Note |\n", "|---|---|---|\n", "| 1st (highest) | `**` | Exponentiation |\n", "| 2nd | `*`, `/`, `//`, `%` | Multiplication, divisions, and modulo |\n", "| 3rd (lowest) | `+`, `-` | Addition and subtraction |\n", "\n", "**Important rules:**\n", "- Operators with the same precedence are evaluated **left to right**\n", "- Use **parentheses `()`** to override the evaluation order\n", "- When in doubt, use parentheses to make the code clearer\n", "\n", "**Precedence examples:**\n", "\n", "```python\n", "# Without parentheses: multiplication before addition\n", "result1 = 2 + 3 * 4\n", "print(result1)\n", "\n", "# With parentheses: we force addition first\n", "result2 = (2 + 3) * 4\n", "print(result2)\n", "\n", "# Complex example\n", "result3 = 2 ** 3 + 4 * 5 - 10 / 2\n", "print(result3)\n", "```\n", "\n", "**Output:**\n", "```\n", "14\n", "20\n", "23.0\n", "```\n", "\n", "### Unary Operators\n", "\n", "Unary operators act on a single value (unlike binary operators, which act on two values). In arithmetic, the most common unary operator is **negation** (`-`), which flips the sign of a number:\n", "\n", "```python\n", "positive_number = 10\n", "negative_number = -positive_number\n", "print(negative_number)\n", "\n", "# Unary operators have high precedence\n", "result = -5 + 2 * 3\n", "print(result)\n", "```\n", "\n", "**Output:**\n", "```\n", "-10\n", "1\n", "```\n", "\n", "**Practical example:**\n", "\n", "```python\n", "# Temperature with a variation\n", "initial_temperature = 25\n", "variation = -3 # Temperature dropped 3 degrees\n", "final_temperature = initial_temperature + variation\n", "print(f\"Initial temperature: {initial_temperature}°C\")\n", "print(f\"Variation: {variation}°C\")\n", "print(f\"Final temperature: {final_temperature}°C\")\n", "```\n", "\n", "**Output:**\n", "```\n", "Initial temperature: 25°C\n", "Variation: -3°C\n", "Final temperature: 22°C\n", "```\n", "\n", "> **Note:** Python has other unary operators, such as bitwise inversion (`~`), which we will see later in the bitwise operations section." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Relational Operators\n", "\n", "Now that we know how to do calculations with arithmetic operators, we need to learn how to **compare values**. That is where relational operators — also known as comparison operators — come in.\n", "\n", "These operators are essential for writing programs that make decisions. For example: checking whether a student passed, whether a product is in stock, whether a password is correct, or whether a user is old enough to access certain content.\n", "\n", "The result of a comparison is always a **boolean** value: `True` or `False`.\n", "\n", "### Relational Operators Table\n", "\n", "| Operator | Symbol | Description | Example | Result |\n", "|---|---|---|---|---|\n", "| **Equality** | `==` | Checks whether two values are equal | `5 == 5` | `True` |\n", "| **Inequality** | `!=` | Checks whether two values are different | `5 != 3` | `True` |\n", "| **Less than** | `<` | Checks whether the first is less than the second | `3 < 5` | `True` |\n", "| **Greater than** | `>` | Checks whether the first is greater than the second | `3 > 5` | `False` |\n", "| **Less than or equal** | `<=` | Checks whether the first is less than or equal to the second | `3 <= 5` | `True` |\n", "| **Greater than or equal** | `>=` | Checks whether the first is greater than or equal to the second | `5 >= 5` | `True` |\n", "\n", "```{admonition} Warning - Equality vs Assignment\n", ":class: warning\n", "Don't confuse the equality operator `==` (two equal signs) with the assignment operator `=` (one equal sign). The first **compares** values, the second **assigns** values!\n", "```\n", "\n", "### Basic Examples\n", "\n", "Let's see how to use these operators in practice:\n", "\n", "```python\n", "# Comparing numbers\n", "grade = 7.5\n", "average = 6.0\n", "\n", "print(f\"Grade equal to average? {grade == average}\")\n", "print(f\"Grade different from average? {grade != average}\")\n", "print(f\"Grade greater than average? {grade > average}\")\n", "print(f\"Grade greater than or equal to 7? {grade >= 7}\")\n", "print(f\"Grade less than 5? {grade < 5}\")\n", "```\n", "\n", "**Output:**\n", "```\n", "Grade equal to average? False\n", "Grade different from average? True\n", "Grade greater than average? True\n", "Grade greater than or equal to 7? True\n", "Grade less than 5? False\n", "```\n", "\n", "### String Comparison\n", "\n", "Comparisons don't only work with numbers. We can also compare strings! The comparison follows **lexicographic order** (alphabetical order), based on the Unicode values of the characters.\n", "\n", "```python\n", "name1 = \"Anna\"\n", "name2 = \"Bruno\"\n", "name3 = \"Anna\"\n", "\n", "print(f\"'{name1}' is equal to '{name3}'? {name1 == name3}\")\n", "print(f\"'{name1}' is different from '{name2}'? {name1 != name2}\")\n", "print(f\"'{name1}' comes before '{name2}'? {name1 < name2}\")\n", "```\n", "\n", "**Output:**\n", "```\n", "'Anna' is equal to 'Anna'? True\n", "'Anna' is different from 'Bruno'? True\n", "'Anna' comes before 'Bruno'? True\n", "```\n", "\n", "**Important points about string comparison:**\n", "- Comparison is **case-sensitive**: `\"Python\" != \"python\"`\n", "- Uppercase letters come before lowercase ones in Unicode order\n", "- To ignore case, convert the strings: `text.lower()` or `text.upper()`\n", "\n", "```python\n", "# Case-sensitive comparison\n", "print(\"Python\" == \"python\")\n", "\n", "# Case-insensitive comparison\n", "text1 = \"Python\"\n", "text2 = \"python\"\n", "print(text1.lower() == text2.lower())\n", "```\n", "\n", "**Output:**\n", "```\n", "False\n", "True\n", "```\n", "\n", "### Practical Examples\n", "\n", "**Example 1: Student approval system**\n", "\n", "```python\n", "final_grade = float(input(\"Enter the student's final grade: \"))\n", "minimum_average = 7.0\n", "\n", "if final_grade >= minimum_average:\n", " print(f\"Student PASSED with grade {final_grade}\")\n", "else:\n", " print(f\"Student FAILED with grade {final_grade}\")\n", "```\n", "\n", "**Sample run:**\n", "```\n", "Enter the student's final grade: 8.5\n", "Student PASSED with grade 8.5\n", "```\n", "\n", "**Example 2: Age validation**\n", "\n", "```python\n", "age = int(input(\"Enter your age: \"))\n", "minimum_age = 18\n", "\n", "if age >= minimum_age:\n", " print(\"Access granted.\")\n", "else:\n", " years_remaining = minimum_age - age\n", " print(f\"Access denied. You must be at least {minimum_age} years old.\")\n", " print(f\"{years_remaining} year(s) remaining.\")\n", "```\n", "\n", "**Sample run:**\n", "```\n", "Enter your age: 16\n", "Access denied. You must be at least 18 years old.\n", "2 year(s) remaining.\n", "```\n", "\n", "**Example 3: Login validation**\n", "\n", "```python\n", "correct_user = \"admin\"\n", "correct_password = \"1234\"\n", "\n", "user = input(\"Username: \")\n", "password = input(\"Password: \")\n", "\n", "if user == correct_user and password == correct_password:\n", " print(\"Login successful!\")\n", "else:\n", " print(\"Incorrect username or password.\")\n", "```\n", "\n", "**Sample run:**\n", "```\n", "Username: admin\n", "Password: 1234\n", "Login successful!\n", "```\n", "\n", "### Combining Comparisons\n", "\n", "Relational operators are often used with conditional structures (`if`, `elif`, `else`) and can be combined with logical operators (`and`, `or`, `not`), which we will see in the next section.\n", "\n", "Relational operators are the foundation for building intelligent programs that make decisions. They work together with conditional structures to control program flow based on different situations.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Logical Operators\n", "\n", "We saw that relational operators let us make simple comparisons. But what if we need to check **multiple conditions at the same time**? For example: \"Is the user older than 18 **AND** does she have a driver's license?\" or \"Was the payment made by card **OR** by PIX?\".\n", "\n", "For those situations, we use **logical operators**. They let us combine several boolean conditions into a single expression, building more complex and powerful logic.\n", "\n", "### Logical Operators Table\n", "\n", "| Operator | Symbol | Description | Example | Result | Precedence |\n", "|---|---|---|---|---|---|\n", "| **Logical AND** | `and` | Returns `True` only if **both** conditions are true | `True and False` | `False` | Medium |\n", "| **Logical OR** | `or` | Returns `True` if **at least one** of the conditions is true | `True or False` | `True` | Low |\n", "| **Negation** | `not` | Inverts the boolean value | `not True` | `False` | High |\n", "\n", "### Understanding Each Operator\n", "\n", "**`and` Operator (Logical AND)**\n", "\n", "The `and` operator requires **all** conditions to be true:\n", "\n", "```python\n", "age = 20\n", "has_license = True\n", "\n", "can_drive = (age >= 18) and has_license\n", "print(can_drive)\n", "```\n", "\n", "**Output:**\n", "```\n", "True\n", "```\n", "\n", "**Truth Table for `and`:**\n", "\n", "| Condition A | Condition B | A and B |\n", "|------------|------------|---------|\n", "| `True` | `True` | `True` |\n", "| `True` | `False` | `False` |\n", "| `False` | `True` | `False` |\n", "| `False` | `False` | `False` |\n", "\n", "**`or` Operator (Logical OR)**\n", "\n", "The `or` operator needs **at least one** condition to be true:\n", "\n", "```python\n", "has_card = False\n", "has_cash = True\n", "\n", "can_pay = has_card or has_cash\n", "print(can_pay)\n", "```\n", "\n", "**Output:**\n", "```\n", "True\n", "```\n", "\n", "**Truth Table for `or`:**\n", "\n", "| Condition A | Condition B | A or B |\n", "|------------|------------|---------|\n", "| `True` | `True` | `True` |\n", "| `True` | `False` | `True` |\n", "| `False` | `True` | `True` |\n", "| `False` | `False` | `False` |\n", "\n", "**`not` Operator (Negation)**\n", "\n", "The `not` operator inverts the boolean value:\n", "\n", "```python\n", "is_raining = False\n", "go_running = not is_raining\n", "print(go_running)\n", "```\n", "\n", "**Output:**\n", "```\n", "True\n", "```\n", "\n", "**Truth Table for `not`:**\n", "\n", "| Condition | not Condition |\n", "|----------|--------------|\n", "| `True` | `False` |\n", "| `False` | `True` |\n", "\n", "### Precedence of Logical Operators\n", "\n", "When we combine multiple logical operators, they are evaluated in this order:\n", "1. **`not`** (highest precedence)\n", "2. **`and`** (medium precedence)\n", "3. **`or`** (lowest precedence)\n", "\n", "```python\n", "# Example without parentheses\n", "result1 = True or True and False\n", "print(result1)\n", "\n", "# Example with parentheses (we change the order)\n", "result2 = (True or True) and False\n", "print(result2)\n", "```\n", "\n", "**Output:**\n", "```\n", "True\n", "False\n", "```\n", "\n", "```{admonition} Tip - Code Clarity\n", ":class: tip\n", "Even when not required, use parentheses to make your expressions clearer and easier to read!\n", "```\n", "\n", "### Practical Examples\n", "\n", "**Example 1: Check whether a number is in a range**\n", "\n", "```python\n", "grade = float(input(\"Enter the grade (0-10): \"))\n", "\n", "# Check whether the grade is between 0 and 10\n", "valid_grade = (grade >= 0) and (grade <= 10)\n", "\n", "if valid_grade:\n", " print(f\"Grade {grade} is valid!\")\n", "else:\n", " print(f\"Grade {grade} is invalid! Enter a value between 0 and 10.\")\n", "```\n", "\n", "**Sample run:**\n", "```\n", "Enter the grade (0-10): 8.5\n", "Grade 8.5 is valid!\n", "```\n", "\n", "**Example 2: Checking multiple payment methods**\n", "\n", "```python\n", "payment_method = input(\"Payment method (card/cash/pix): \").lower()\n", "\n", "# Accepts any of the three methods\n", "payment_accepted = (payment_method == \"card\") or \\\n", " (payment_method == \"cash\") or \\\n", " (payment_method == \"pix\")\n", "\n", "if payment_accepted:\n", " print(\"Payment accepted!\")\n", "else:\n", " print(\"Payment method not accepted.\")\n", "```\n", "\n", "**Sample run:**\n", "```\n", "Payment method (card/cash/pix): pix\n", "Payment accepted!\n", "```\n", "\n", "**Example 3: Access system with multiple validations**\n", "\n", "```python\n", "age = int(input(\"Enter your age: \"))\n", "has_authorization = input(\"Do you have parental authorization? (yes/no): \").lower() == \"yes\"\n", "\n", "# Can enter if: age 18+ OR (under 18 BUT has authorization)\n", "can_enter = (age >= 18) or (age < 18 and has_authorization)\n", "\n", "if can_enter:\n", " print(\"Access granted!\")\n", "else:\n", " print(\"Access denied. People under 18 need authorization.\")\n", "```\n", "\n", "**Sample run:**\n", "```\n", "Enter your age: 16\n", "Do you have parental authorization? (yes/no): yes\n", "Access granted!\n", "```\n", "\n", "**Example 4: Strong-password validation**\n", "\n", "```python\n", "password = input(\"Enter your password: \")\n", "\n", "# Criteria for a strong password\n", "has_min_chars = len(password) >= 8\n", "has_digit = any(char.isdigit() for char in password)\n", "has_letter = any(char.isalpha() for char in password)\n", "\n", "# Password is strong if it meets ALL criteria\n", "strong_password = has_min_chars and has_digit and has_letter\n", "\n", "if strong_password:\n", " print(\"Strong password! Registration successful.\")\n", "else:\n", " print(\"Weak password! Use at least 8 characters, including letters and numbers.\")\n", "```\n", "\n", "**Sample run:**\n", "```\n", "Enter your password: python123\n", "Strong password! Registration successful.\n", "```\n", "\n", "**Example 5: Using `not` to invert a condition**\n", "\n", "```python\n", "age = int(input(\"Enter your age: \"))\n", "\n", "# Check whether NOT of legal age\n", "if not (age >= 18):\n", " print(\"You are a minor.\")\n", "else:\n", " print(\"You are an adult.\")\n", "```\n", "\n", "**Sample run:**\n", "```\n", "Enter your age: 16\n", "You are a minor.\n", "```\n", "\n", "### Simplifying Logical Expressions\n", "\n", "Sometimes we can simplify our logical expressions. For example:\n", "\n", "```python\n", "x = 5\n", "# More verbose form\n", "if (x > 0) == True:\n", " print(\"Positive\")\n", "\n", "# Simplified form (better)\n", "if x > 0:\n", " print(\"Positive\")\n", "\n", "# Another example\n", "age = 20\n", "# More verbose form\n", "if not (age < 18):\n", " print(\"Adult\")\n", "\n", "# Simplified form (better)\n", "if age >= 18:\n", " print(\"Adult\")\n", "```\n", "\n", "### Putting It All Together\n", "\n", "Logical operators are extremely powerful when combined with relational operators:\n", "\n", "```python\n", "# Store discount system\n", "purchase_value = float(input(\"Purchase value: $ \"))\n", "is_vip_customer = input(\"Is a VIP customer? (yes/no): \").lower() == \"yes\"\n", "first_purchase = input(\"Is this the first purchase? (yes/no): \").lower() == \"yes\"\n", "\n", "# 20% discount for VIP OR first purchase above $ 100\n", "has_discount = is_vip_customer or (first_purchase and purchase_value > 100)\n", "\n", "if has_discount:\n", " final_value = purchase_value * 0.8 # 20% discount\n", " print(f\"You got a 20% discount!\")\n", " print(f\"Final value: $ {final_value:.2f}\")\n", "else:\n", " print(f\"Final value: $ {purchase_value:.2f}\")\n", "```\n", "\n", "Logical operators are essential for building programs that make complex decisions based on multiple conditions. Mastering them lets you write more sophisticated code and solve real-world problems!\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ternary Operator (Conditional Expression)\n", "\n", "When you need to **choose between two values** depending on a condition, Python offers the **ternary operator**, also called a **conditional expression**. It lets you write in **a single line** what we would normally do with `if/else` across multiple lines.\n", "\n", "### Syntax\n", "\n", "```text\n", "value_if_true if condition else value_if_false\n", "```\n", "\n", "The reading is direct: \"use `value_if_true` **if** the condition is true, **otherwise** use `value_if_false`\".\n", "\n", "### Basic Example\n", "\n", "Suppose we want to classify a number as \"even\" or \"odd\":\n", "\n", "```python\n", "number = 10\n", "classification = \"even\" if number % 2 == 0 else \"odd\"\n", "print(f\"{number} is {classification}\")\n", "```\n", "\n", "**Output:**\n", "```\n", "10 is even\n", "```\n", "\n", "The equivalent block `if/else` version would be longer:\n", "\n", "```python\n", "number = 10\n", "if number % 2 == 0:\n", " classification = \"even\"\n", "else:\n", " classification = \"odd\"\n", "print(f\"{number} is {classification}\")\n", "```\n", "\n", "Both forms produce the same result — the ternary just condenses the logic into a single expression that **produces a value**.\n", "\n", "The figure below shows the three operands and the order Python evaluates them in.\n", "\n", "```{image} ternario-light.png\n", ":alt: Two panels. In the first, the expression even if number modulo 2 equals zero else odd, with brackets under the three operands and numbered dots above them, the number one over the condition in the middle of the line, the two over the left value and the three over the right value. Two arrows leave the condition below the line and rise to each of the values, labelled True on the left and False on the right. In the second panel, the same expression with the number ten in place of the variable, the condition evaluating to True, the right value dimmed and a straight arrow going down from the left value to the word even\n", ":class: only-light\n", "```\n", "\n", "```{image} ternario-dark.png\n", ":alt: Two panels. In the first, the expression even if number modulo 2 equals zero else odd, with brackets under the three operands and numbered dots above them, the number one over the condition in the middle of the line, the two over the left value and the three over the right value. Two arrows leave the condition below the line and rise to each of the values, labelled True on the left and False on the right. In the second panel, the same expression with the number ten in place of the variable, the condition evaluating to True, the right value dimmed and a straight arrow going down from the left value to the word even\n", ":class: only-dark\n", "```\n", "\n", "### Why Is It Called \"Ternary\"?\n", "\n", "Most operators we have seen so far are **binary** (they act on two values: `2 + 3`, `x and y`). We have also seen **unary** operators (acting on a single value: `-x`, `not x`). The **ternary** operator acts on **three operands**: the value returned when the condition is true, the condition itself, and the value returned when the condition is false.\n", "\n", "### More Examples\n", "\n", "**Example 1: Discount based on a minimum amount**\n", "\n", "```python\n", "purchase_amount = 250\n", "discount = 0.10 if purchase_amount > 200 else 0.05\n", "print(f\"Discount: {discount * 100:.0f}%\")\n", "```\n", "\n", "**Output:**\n", "```\n", "Discount: 10%\n", "```\n", "\n", "**Example 2: Pass/fail message**\n", "\n", "```python\n", "grade = 7.5\n", "result = \"Approved\" if grade >= 6 else \"Failed\"\n", "print(result)\n", "```\n", "\n", "**Output:**\n", "```\n", "Approved\n", "```\n", "\n", "**Example 3: Absolute value without `abs()`**\n", "\n", "```python\n", "x = -8\n", "modulus = x if x >= 0 else -x\n", "print(modulus)\n", "```\n", "\n", "**Output:**\n", "```\n", "8\n", "```\n", "\n", "### Nesting (Use With Care)\n", "\n", "Ternaries can be chained, but readability drops fast. When you need more than two options, prefer block `if/elif/else` (which we will see in the next chapter):\n", "\n", "```python\n", "grade = 8.5\n", "concept = \"A\" if grade >= 9 else \"B\" if grade >= 7 else \"C\" if grade >= 5 else \"D\"\n", "print(concept)\n", "```\n", "\n", "**Output:**\n", "```\n", "B\n", "```\n", "\n", "**How to read the chain.** The `else` of a ternary accepts any expression, and a ternary is an expression. So what comes after the first `else` is **another whole ternary**, and so on. Writing the parentheses Python assumes makes it visible:\n", "\n", "```text\n", "\"A\" if grade >= 9 else (\"B\" if grade >= 7 else (\"C\" if grade >= 5 else \"D\"))\n", "```\n", "\n", "Evaluation follows the same rule as the basic example, one level at a time: it tests `grade >= 9`; since that is false, the value of the expression becomes the ternary inside the first parentheses, which tests `grade >= 7`. Since `8.5 >= 7` is true, the result is `\"B\"` and the remaining levels are never even read.\n", "\n", "**The same decision as a block.** Each `else` followed by a new ternary becomes an `elif`, and the last `else` stays as the final `else`:\n", "\n", "```python\n", "grade = 8.5\n", "if grade >= 9:\n", " concept = \"A\"\n", "elif grade >= 7:\n", " concept = \"B\"\n", "elif grade >= 5:\n", " concept = \"C\"\n", "else:\n", " concept = \"D\"\n", "print(concept)\n", "```\n", "\n", "**Output:**\n", "```\n", "B\n", "```\n", "\n", "Both forms produce the same result for any grade. The difference is that the block version puts each condition at the start of a line, in the order they are tested, while the chained one forces you to read to the end to find out how many levels there are.\n", "\n", "```{admonition} Tip - When to use the ternary\n", ":class: tip\n", "- **Use it** when the choice between two values fits comfortably on one line and makes the code more direct.\n", "- **Avoid it** when the condition or the values are long — block `if/else` reads better.\n", "- Remember that the ternary is an **expression** (it produces a value that can be assigned or passed to a function), while block `if/else` is a **statement** (it executes code). This difference becomes important in the next chapter, when we combine ternaries with list comprehensions.\n", "```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Membership Operators\n", "\n", "So far, we have learned how to do calculations, comparisons, and combine conditions. But we often need to check whether an element **belongs** or **does not belong** to a collection of data. For example: checking whether a letter is in a word, whether a name is in a list of approved candidates, or whether a product is available in stock.\n", "\n", "For these situations, Python provides the **membership operators**: `in` and `not in`.\n", "\n", "### Membership Operators Table\n", "\n", "| Operator | Symbol | Description | Example | Result |\n", "|---|---|---|---|---|\n", "| **Member of** | `in` | Checks if a value is present in the sequence | `'a' in 'python'` | `False` |\n", "| **Not member of** | `not in` | Checks if a value is not present in the sequence | `'a' not in 'python'` | `True` |\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
Visual demonstration of the in and not in operators
\n", "