2  Constants and Variables in Python

In Python, variables and constants are fundamental concepts used to store and manipulate data. Understanding these concepts is essential for writing effective and efficient code.

2.1 Variables in Python

A variable is a named location in memory used to store data that can change during the execution of a program. Variables can hold different types of data, such as numbers, strings, or more complex data structures.

2.1.1 Declaring Variables

To declare a variable in Python, you simply assign a value to a name using the assignment operator =. Python is dynamically typed, meaning you do not need to declare the type of the variable explicitly.

# Variable declaration
x = 10           # An integer variable
name = "Alice"   # A string variable
pi = 3.14159     # A float variable

print(x)         # Output: 10
print(name)      # Output: Alice
print(pi)        # Output: 3.14159
# Updating variable values
x = 20           # Reassigning a new value to x
name = "Bob"     # Changing the value of name

print(x)         # Output: 20
print(name)      # Output: Bob

2.2 Constants in Python

A constant is a value that does not change during the execution of a program. Python does not have a built-in way to define constants explicitly, but naming conventions are used to indicate that a variable should be treated as a constant.

2.2.1 Defining Constants

Python does not have a specific syntax for defining constants. However, by convention, constants are written in all uppercase letters, and these variables are not supposed to be modified.

# Defining constants (by convention)
MAX_SPEED = 120          # A constant integer
GRAVITY = 9.81           # A constant float
WELCOME_MESSAGE = "Hello" # A constant string

print(MAX_SPEED)         # Output: 120
print(GRAVITY)           # Output: 9.81
print(WELCOME_MESSAGE)   # Output: Hello

3 Data Types in Python

In Python, data types are used to classify the type of data that a variable holds. Understanding data types is essential because it helps you manage data efficiently and perform operations suited to the type of data you are working with.

Python has several built-in data types, which can be grouped into the following categories:

  1. Numeric Types: int, float, complex
  2. Sequence Types: str, list, tuple
  3. Mapping Type: dict
  4. Set Types: set, frozenset
  5. Boolean Type: bool
  6. Binary Types: bytes, bytearray, memoryview

3.1 Numeric Data Types

3.1.1 Integer (int)

Integers are whole numbers, positive or negative, without decimals.

# Integer example
age = 25
print(age)        # Output: 25
print(type(age))  # Output: <class 'int'>

3.1.2 Float (float)

Floats represent numbers with decimal points.

# Float example
height = 5.9
print(height)        # Output: 5.9
print(type(height))  # Output: <class 'float'>

3.1.3 Complex (complex)

Complex numbers consist of a real and an imaginary part.

# Complex number example
z = 3 + 4j
print(z)            # Output: (3+4j)
print(type(z))      # Output: <class 'complex'>

3.2 Sequence Data Types

3.2.1 String (str)

Strings are sequences of characters enclosed in quotes.

# String example
name = "Python"
print(name)        # Output: Python
print(type(name))  # Output: <class 'str'>

3.2.2 List (list)

Lists are ordered, mutable collections of items that can hold mixed data types.

# List example
fruits = ["apple", "banana", "cherry"]
print(fruits)        # Output: ['apple', 'banana', 'cherry']
print(type(fruits))  # Output: <class 'list'>

3.2.2.1 List Indexing and Slicing

Indexing allows you to access individual elements in a list using their position, while slicing lets you extract a sublist from a list.

3.2.2.1.1 Indexing

Indexing starts at 0. Negative indices can be used to access elements from the end of the list.

# List indexing example
fruits = ['apple', 'banana', 'cherry']

# Accessing elements
print(fruits[0])  # Output: apple
print(fruits[-1]) # Output: cherry
3.2.2.1.2 Slicing

Slicing allows you to extract a range of elements. The syntax is list[start:end], where start is inclusive and end is exclusive.

# List slicing example
numbers = [0, 1, 2, 3, 4, 5]

# Extracting a sublist
print(numbers[1:4])   # Output: [1, 2, 3]
print(numbers[:3])    # Output: [0, 1, 2] (from the start to index 2)
print(numbers[3:])    # Output: [3, 4, 5] (from index 3 to the end)
print(numbers[-3:])   # Output: [3, 4, 5] (last three elements)

3.2.2.2 Adding Elements to a List

You can add elements to a list using methods like append(), insert(), and extend().

3.2.2.2.1 Using append()

append() adds an element to the end of the list.

# Using append() to add an element
numbers = [1, 2, 3]
numbers.append(4)
print(numbers)  # Output: [1, 2, 3, 4]
3.2.2.2.2 Using insert()

insert() adds an element at a specified position.

# Using insert() to add an element at a specific position
numbers = [1, 3, 4]
numbers.insert(1, 2)  # Insert 2 at index 1
print(numbers)  # Output: [1, 2, 3, 4]
3.2.2.2.3 Using extend()

extend() adds multiple elements to the end of the list.

# Using extend() to add multiple elements
numbers = [1, 2]
numbers.extend([3, 4, 5])
print(numbers)  # Output: [1, 2, 3, 4, 5]

3.2.2.3 Modifying and Deleting List Elements

You can modify or remove elements from a list using index assignments, remove(), pop(), or del.

3.2.2.3.1 Modifying Elements

Assign a new value to an index to modify an element.

# Modifying an element in the list
numbers = [1, 2, 3]
numbers[1] = 20
print(numbers)  # Output: [1, 20, 3]
3.2.2.3.2 Deleting Elements

Use remove() to delete an element by value, pop() to remove by index, or del to delete a slice.

# Using remove() to delete by value
numbers = [1, 2, 3, 4]
numbers.remove(3)
print(numbers)  # Output: [1, 2, 4]

# Using pop() to delete by index
numbers = [1, 2, 3, 4]
removed_element = numbers.pop(1)
print(numbers)  # Output: [1, 3, 4]
print(removed_element)  # Output: 2

# Using del to delete by index or slice
numbers = [1, 2, 3, 4, 5]
del numbers[1:3]
print(numbers)  # Output: [1, 4, 5]

3.2.2.4 Sorting Lists

Use sort() to sort a list in place, or sorted() to return a new sorted list.

# Sorting a list in ascending order
numbers = [3, 1, 4, 1, 5]
numbers.sort()
print(numbers)  # Output: [1, 1, 3, 4, 5]

# Sorting a list in descending order
numbers.sort(reverse=True)
print(numbers)  # Output: [5, 4, 3, 1, 1]

# Using sorted() to return a new sorted list
new_numbers = sorted(numbers)
print(new_numbers)  # Output: [1, 1, 3, 4, 5]

3.2.3 3. Tuple (tuple)

A tuple is an ordered, immutable collection of elements. Tuples are similar to lists but cannot be modified after creation.

# Creating and accessing tuples
coordinates = (10, 20)
print(coordinates)        # Output: (10, 20)
print(coordinates[0])     # Output: 10

# Tuples are immutable; attempting to modify will raise an error
# coordinates[0] = 30  # This would cause an error

3.3 Mapping Data Type

3.3.1 Dictionary (dict)

A dictionary is a collection of key-value pairs, where each key is unique. Dictionaries are mutable, allowing for dynamic updates.

# Dictionary example
person = {"name": "Alice", "age": 30}
print(person)        # Output: {'name': 'Alice', 'age': 30}
print(type(person))  # Output: <class 'dict'>

3.3.1.1 Accessing Values Using Keys

Access values in a dictionary using keys.

# Accessing values using keys
name = person["name"]
age = person.get("age")
print(name)  # Output: Alice
print(age)   # Output: 30

3.3.1.2 Adding and Removing Key-Value Pairs

You can add new key-value pairs or remove existing ones using methods like update(), del, or pop().

3.3.1.2.1 Adding Key-Value Pairs
# Adding new key-value pairs
person["city"] = "New York"
print(person)  # Output: {'name': 'Alice', 'age': 30, 'city': 'New York'}
3.3.1.2.2 Removing Key-Value Pairs
# Removing a key-value pair using pop()
removed_value = person.pop("age")
print(person)        # Output: {'name': 'Alice', 'city': 'New York'}
print(removed_value) # Output: 30

# Removing a key-value pair using del
del person["city"]
print(person)  # Output: {'name': 'Alice'}

3.4 Set Data Types

3.4.1 Set (set)

Sets are unordered collections of unique items.

# Set example
numbers = {1, 2, 3, 4}
print(numbers)        # Output: {1, 2, 3, 4}
print(type(numbers))  # Output: <class 'set'>

3.5 Boolean Data Type

3.5.1 Boolean (bool)

Booleans represent one of two values: True or False.

# Boolean example
is_active = True
print(is_active)        # Output: True
print(type(is_active))  # Output: <class 'bool'>

3.6 f-string Formatting in Python

f-strings, introduced in Python 3.6, are a modern and powerful way to format strings. They offer a concise and readable syntax, allowing you to embed expressions directly inside string literals by prefixing the string with the letter f or F.

f-strings make string formatting simpler and more intuitive compared to older methods such as % formatting or the str.format() method. They allow for inline expression evaluation, formatting of numbers, and easy manipulation of string data.

3.6.1 Embedding Variables

To use f-strings, simply place an f before the opening quote of the string and include expressions inside curly braces {}.

# Basic usage of f-string
name = "Alice"
age = 30

# Embedding variables in a string
greeting = f"Hello, {name}! You are {age} years old."
print(greeting)  # Output: Hello, Alice! You are 30 years old.

3.6.2 Inline Expressions

f-strings allow you to include any valid Python expression inside the curly braces.

# Using expressions inside f-strings
x = 10
y = 5

# Inline arithmetic expression
result = f"{x} + {y} = {x + y}"
print(result)  # Output: 10 + 5 = 15

3.7 Advanced Formatting with f-strings

3.7.1 Number Formatting

f-strings provide options to format numbers in various ways, such as controlling decimal places, adding commas, or displaying percentages.

3.7.1.1 Formatting Floats

You can specify the number of decimal places by using .nf, where n is the number of decimal places.

# Formatting a float to 2 decimal places
pi = 3.14159265358979
formatted_pi = f"Pi rounded to 2 decimal places: {pi:.2f}"
print(formatted_pi)  # Output: Pi rounded to 2 decimal places: 3.14

3.7.1.2 Adding Commas to Large Numbers

Use the :, format specifier to include commas as thousand separators.

# Adding commas to large numbers
large_number = 1000000
formatted_number = f"The number is: {large_number:,}"
print(formatted_number)  # Output: The number is: 1,000,000

3.7.1.3 Displaying Percentages

To display a number as a percentage, use the % format specifier.

# Displaying a percentage
success_rate = 0.85
formatted_rate = f"Success rate: {success_rate:.2%}"
print(formatted_rate)  # Output: Success rate: 85.00%

3.7.2 Embedding Dictionary Values

f-strings can also be used to format values from dictionaries.

# Formatting dictionary values
person = {"name": "Bob", "age": 40}
formatted_string = f"{person['name']} is {person['age']} years old."
print(formatted_string)  # Output: Bob is 40 years old.