Page cover image

🐍Python

Personal Python notes authored by me, encompassing indexing, loops, functions, data types, and formatting essentials, continually updated

Python Notes

name = "Akash Kumar"
print(len(name))  # Outputs the length of the string
print(name[1:5])  # Outputs the substring from index 1 to 4 (excluding index 5)
print(name[1:-1])  # Outputs the substring from index 1 to the second last character

Indexing in Python:

  • Index -1 refers to the last character in a string, while -5 refers to the character 'K' in 'Kumar'.

  • Positive indexes start from 0, denoting the first character, 1 for the second, and so on.

Slicing in Python:

  • [1:]: Prints the entire string from index 1 to the end.

  • [:3] or [:]: Prints the substring from index 0 to 2 (inclusive of indexes 0, 1, 2).

Arithmetic Operations in Python:

  • / performs division and returns a floating-point number.

  • // performs floor division, returning only the integer part of the quotient.

Augmented Assignment Operator in Python:

  • The statement x = x + 1 is equivalent to x += 1.

Working with Numbers in Python:

  • round(2.9) returns 3.

  • abs(-2.9) returns 2.9 in its positive form.

Math Functions in Python:

  • math.ceil(1.2) returns 2.

  • math.ceil(2.4) returns 3.

Array Creation:

import array as ar
numbersArray = ar.array('i', [1, 2, 3, 4, 5, 6])  # Creating an array of integers

Python Data Types and Ordering

Built-in Functions:

  • int()

  • str()

  • float()

  • bool() - Some values are meant to be falsy like:

    • 0

    • None

    • ""

Primitive Types in Python:

  1. Strings

  2. Numbers:

  3. int, float, complex numbers

  4. Boolean

Lexicographical Order:

  • "bag" == "BAG" is False because even though they appear the same, in programming, they are represented by different numbers, like ord("b").

ASCII Representation:

  • For uppercase letters:

    • From 65 to 90 (ASCII)

    • For lowercase letters: From 97 to 122

    • For numbers: From 48 to 57 (0 to 9)

  • Ascii Uppercase Alphabet Print:

import string
import time

for i in string.ascii_uppercase:
    print(f"{i} => {ord(i)}")
    time.sleep(0.5)
  • Range of ASCII Uppercase Letters:

for i in range(65, 91):
    print(chr(i))
    time.sleep(0.3)

TERNARY OPERATOR

if age >= 18:
    print("Eligible")
else:
    print("Not Eligible")
message = "Eligible" if age >= 18 else "Not Eligible"

Logical Operators in Python

In Python, logical operators exhibit short-circuit behavior. For and operators, if the first operand is False, the evaluation stops as the whole condition will be False. Similarly, for or operators, if the first operand is True, the evaluation stops as the whole condition will be True.

Example:

income and score and student
income or score or student

if age >= 18 and age < 65:
    print("")
if 18 <= age < 65:
    print("")

Range Function in Python

The range() function in Python can be used with different parameters. Both range(3) and range(0, 3) result in the same iteration: starting from 0 and iterating 3 times.

The range() function follows this structure:

  • range(start, stop, step)

For example, range(1, end+1) starts from 1 (inclusive) and iterates until end+1 (exclusive), effectively repeating end times.

Example usage:

range(0, 21, 2)  # Generates a sequence of multiples of 2

For-Else Loop in Python

In Python, the for-else loop is a construct used to execute a block of code in the scenario where the for loop completes its iterations without encountering a break statement.

Syntax:

for item in iterable:
    if condition:
        # Perform operations
        break
else:
    # Execute this block if the loop completes without encountering a break
    # Operations to perform when the loop completes without a break
  • If the for loop is exited via a break statement, the else block will not execute.

  • However, if the loop completes all iterations without encountering a break, the else block will execute.

Functions in Python

Functions in Python are defined using the def keyword followed by the function name and parameters. Arguments can then be passed to these functions when calling them.

Defining a Function

def function_name(these_are_parameters):
    # Function body
    # Perform operations using parameters
    # Return a value using the return statement

Calling a Function


function_name(this_is_arguments)  # Calling a function with arguments
  • By default, arguments in Python functions are required unless default values are specified for them.

Return Statement

  • The return statement in Python functions is used to return a value. If no value is specified, the function returns None. When a function returns a value, it evaluates as True, otherwise, it returns False.

def greet(name):
    return f"Hello, {name}!"

msg = greet("Akash")
print(msg)  # Output: Hello, Akash!
  • Remember that every function in Python returns a value, even if it's None. Functions can be used to perform operations and return specific results or manipulate data.

Keyword Arguments in Python:

  • Keyword arguments allow us to pass arguments to a function using parameter names.

For instance:

print(increment(5, 10))
# This calls the 'increment' function with arguments '5' and '10'

# Alternatively, using keyword arguments:
print(increment(number=5, by=10))
# This achieves the same as the previous call but uses keyword arguments 'number' and 'by'
  • Additionally, default values can be defined for function parameters, allowing us to omit certain arguments:

def increment(number, by=1):
    return number + by

# Here, 'by' has a default value of 1
# If 'by' is not specified, it automatically takes the default value
print(increment(5))  # Output: 6 (5 + 1)
print(increment(5, 3))  # Output: 8 (5 + 3)

Optional Arguments in Python Functions

When defining arguments in Python functions, it's essential to define optional arguments at the end. It's not possible to define a required argument after an optional one.

If we have a scenario where the parameters are not predefined, such as when multiplying multiple numbers, we can utilize the *args technique within the function.

For example:

def multiply(*numbers):
    # This creates an iterable tuple with the numbers passed to the function
    pass  # Perform the necessary operations with the numbers
  • The *numbers parameter here collects all passed arguments into an iterable tuple within the function, allowing flexibility in handling various numbers.

Double Asterisks (**kwargs) in Python

The double asterisks **kwargs in Python save values in a dictionary. This technique, often called "keyword arguments," receives arguments in the form of key-value pairs. For instance:

def sample_function(**kwargs):
    # This allows receiving arguments in a key-value format like id=1, name="Akash", age=22
    pass  # Perform operations with the received key-value pairs
  • The **kwargs parameter collects these keyword arguments into a dictionary within the function. Once collected, you can access and manipulate these values just like you would with a dictionary in Python.

Scope of Variables in Functions

Variables defined within a function are considered local variables. They exist solely within the function's scope and are inaccessible outside it.

However, it's possible to declare the same parameters in different functions without any issues.

To access global variables within a function, you can use the global keyword followed by the variable name. For instance:

message = "a"

def my_function():
    global message
    message = "b"  # Assigning a new value to the global variable 'message'
  • The global keyword allows modification of a global variable within a function, but it's often considered a bad practice due to the potential for unexpected side effects and code complexity.

FizzBuzz Function

This function performs the FizzBuzz operation on a given input number and returns the result.

def fizz_buzz(input):
    inputM = "FizzBUzz" if not input % 3 and not input % 5 else "Fizz" if not input % 3 else "Buzz" if not input % 5 else input

    return inputM

print(fizz_buzz(71))

Lists

  • If we create two lists in a list, then it is called a two-dimensional list.

  • The list() function needs an iterable object and then creates a list of that, like list(range(20)).

  • When printing a list, we can use slicing, denoted by ::. For example, ::2 means it will print the second number and skip the others.

  • If the slicing value is 2, the first index will be printed, and then it will skip the number of counts specified in the slicing value. For instance:

  • 1 2 3 4 5 6 ::2

  • 1 skip 3 skip 5 skip

  • When using 3 as the slicing value, it will skip as follows:

  • 1 skip skip 4 skip skip 7 skip skip 10

  • Using ::1 prints the normal list, and ::-1 prints it in reverse.

Unpacking Lists in Python

Unpacking lists in Python involves assigning values of a list to multiple variables simultaneously.

listNumber = [1, 2, 3, 4, 5]
first = listNumber[0]
second = listNumber[1]
third = listNumber[2]
fourth = listNumber[3]

Unpacking list values to multiple variables in one line

first, second, third, fourth, fifth = listNumber
  • Note: The number of variables on the left side should match the length of the list for successful unpacking.

Unpacking Lists and Extracting Last Number

In Python, unpacking lists allows assigning list values to multiple variables simultaneously. The * operator can be used to capture remaining values.

# Unpacking list values to multiple variables and capturing the remaining values
listNumber = [1, 2, 3, 4, 5]

# Unpacking with *other to capture remaining values
first, second, *other = listNumber
  • This assigns the first and second values according to their indexes and assigns the remaining list elements to the other variable.

# Extracting the last number from a list using unpacking
first, *other, second = listNumber
  • The above code extracts the first and last values while capturing the intermediate values in the other variable.

  • This feature is beneficial when handling lists with a large number of elements or when there's a need to extract specific elements efficiently.

Iterating Lists with Index Using enumerate

When iterating over lists in Python, you can obtain both the index and the value of each element by using the enumerate() function.

listNumber = ["a", "b", "c", "d", "e"]

# Using enumerate to access both index and item in the list
for index, letter in enumerate(listNumber):
    print(index, letter)
  • The enumerate() function generates an index-value tuple for each element in the list during iteration. By unpacking this tuple directly in the loop, you can access both the index and the item of the list simultaneously.

  • This method is convenient when you need to access both the index and the corresponding value while iterating through a list.

List Methods in Python

Python offers several built-in methods to manipulate lists effectively.

Adding Items to Lists

  • list.append(item): Adds an item to the end of the list.

  • list.insert(index, item): Inserts an item at a specified index in the list.

Removing Items from Lists

  • list.pop(): Removes the last item from the list.

  • list.pop(index): Removes the item at the specified index from the list.

  • list.remove(item): Removes the first occurrence of the specified item from the list.

Deleting Items

  • del list[index]: Deletes the item at the specified index.

  • del list[start:end]: Deletes items within a specified range.

  • list.clear(): Removes all items from the list.

Retrieving Item Information

  • list.index(item): Finds the index of the specified item.

  • list.count(item): Counts occurrences of a specific item in the list.

Sorting Lists

  • list.sort(): Sorts the list in ascending order.

  • list.sort(reverse=True): Sorts the list in descending order.

  • sorted(iterable): Returns a new sorted list without modifying the original list.

Example:

lst = [1, 2, 3, 4, 5, 5, 5, 5, 3, 5, 5, 3]

# Count occurrence and print indices of an item
if lst.count(5):
    for index, item in enumerate(lst):
        if item == 5:
            print(f"5 is at index {index}")

Sorting Lists with Key Parameter and Lambda Functions

When dealing with complex data structures like tuples or lists containing multiple items or strings, direct sorting might not work as intended. In Python, the sort() method provides a key parameter to facilitate sorting based on specific criteria.

Using a Function with key Parameter

def read_index(items):
    return items[1]

item = [(1, 'Apple', 30), (3, 'Banana', 20), (2, 'Orange', 25)]

print("Normal List...")
for i in item:
    print(i)

item.sort(key=read_index)
print("Sorted List...")
for i in item:
    print(i)

print("Reverse Sorted")
item.sort(key=read_index, reverse=True)
for i in item:
    print(i)

Lambda Functions for Sorting

  • Instead of defining a separate function, lambda functions (anonymous functions) can be used with the key parameter to achieve the same result more concisely.

item = [(1, 'Apple', 30), (3, 'Banana', 20), (2, 'Orange', 25)]

print("Normal List...")
for i in item:
    print(i)

item.sort(key=lambda items: items[1])
print("Sorted List...")
for i in item:
    print(i)

print("Reverse Sorted")
item.sort(key=lambda items: items[1], reverse=True)
for i in item:
    print(i)

Use Cases of Lambda Functions

  • Lambda functions are versatile and handy, especially when used in scenarios like filtering or sorting complex data:

# Filtering even numbers using lambda
evenNumbers = [2, 5, 7, 10, 12, 15, 17, 20]
filtered = list(filter(lambda x: x % 2 == 0, evenNumbers))

# Sorting dictionaries based on a specific key using lambda and sorted
data = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}, {'name': 'Charlie', 'age': 20}]
sorted_data = sorted(data, key=lambda x: x['age'])
  • Lambda functions offer a concise way to define simple functions inline, making them useful for filtering and sorting operations.

Map Function in Python

The map function in Python requires two parameters: the function and the iterable.

Here is an example using a lambda function with a list containing names and their respective ages:

list1 = [
    ("Akash", 2),
    ("Kumar", 1),
    ("Nar", 8)
]

ages = list(map(lambda item: item[1], list1))
print(ages)

Filter Function in Python

The filter() function in Python takes two arguments: a function (which can be a lambda function or a defined function that returns a boolean value) and an iterable.

An example of using filter() with a lambda function to filter even numbers from a list:

even_numbers = list(filter(lambda num: not num % 2, ll))
  • This code snippet demonstrates how to filter even numbers from a list (ll) using the filter() function with a lambda function and convert the result to a list for further processing.

List Comprehension in Python

List comprehension is a concise and powerful way to create lists in Python.

Consider the following example:

list1 = [
    ("Akash", 2),
    ("Kumar", 1),
    ("Nar", 8)
]

Extracting names and ages from a list of tuples

names = [i[0] for i in list1]
ages = [j[1] for j in list1]
print(names)
print(ages)

Iterating through names and ages using a loop

for i in range(3):
    print(f"Names => {names[i]} || Ages => {ages[i]}")

Using list comprehension for filtering based on a condition

agess = [item for item in list1 if not item[1] > 4]

Additional list examples

list1 = [1, 2, 3]
list2 = ['a', 'b', 'c', 'd']
list3 = ['x', 'y', 'z']
list4 = list("AKash Kumar")

Function For Zip

def functionForZip(*lists):
    zipped = []

    minimumLoopWeCanDo = min(len(line) for line in lists)

    for i in range(minimumLoopWeCanDo):
        tupleToBeAdded = tuple(tupleNo[i] for tupleNo in lists)
        # The tuple before the list comprehension function is important.
        # In every loop, it takes the i'th list and uses it as tupleNo, referencing that loop.
        # It then takes the i'th index from that list and runs as much as the quantity of the lists.
        # Before adding it to the zip, it completes the tuple because of the for loop.
        zipped.append(tupleToBeAdded)

    return zipped

result = functionForZip(list1, list2, list3, list4)
print(result)

Stacks in programming operate on the principle of Last-In, First-Out (LIFO).

  • Items are added or pushed at the end of the stack, and the last added item is the first to be removed.

  • Use 'append' to insert an item into the stack.

  • Use 'pop' to remove the last item.

  • 'not' with the list name acts as a boolean function for checking if the stack is empty.

  • '-1' index refers to the last value in the stack.

  • Conceptually similar to a mobile browsing session where the last visited pages are accessible first.

Similar to stacks, a queue follows the First-In, First-Out (FIFO) principle.

  • 'deque' is an efficient double-ended queue for removing elements from the front and back.

  • 'Queue' needs to be imported and operates on the first item added, which is the first to be retrieved.

from queue import Queue

# Creating a Queue object
my_queue = Queue()

# Enqueuing elements into the queue
my_queue.put(10)
my_queue.put(20)
my_queue.put(30)

# Dequeuing elements from the queue (FIFO order)
print(my_queue.get())  # Output: 10
print(my_queue.get())  # Output: 20
print(my_queue.get())  # Output: 30

# Demonstrating a new Queue object
new_queue = Queue()

new_queue.put(10)
print(new_queue.get())  # Output: 10
new_queue.put(200)
new_queue.put(30)
print(new_queue.get())  # Output: 200
  • This example illustrates how a queue behaves, enqueuing and dequeuing elements in a first-in, first-out order using Python's Queue module.

Tuples in Python

Tuples in Python can be defined using parentheses () or without them. For instance:

  • tupleNumbers = 1, 2, 4 is a tuple.

  • If it's a single value tuple, ensure a comma is included at the end: singleValueTuple = 5,

Operations on Tuples

Operations on tuples include:

  • Concatenation: newTuple = tuple1 + tuple2

  • Multiplication: multipliedTuple = tuple1 * 3

Converting to Tuples

Converting other iterables to a tuple:

  • Use tuple() function: tuple_from_list = tuple([1, 2, 3]) or tuple_from_string = tuple("hello")

Iterating Over Strings to Create a Tuple

Strings can be directly iterated to obtain a tuple: my_string = "hello"; tuple_from_string = tuple(my_string)

Swapping Variables in Python

In Python, swapping the values of two variables is often done in a single line without using a temporary variable. For instance:

x = 10
y = 11

# Traditional swapping method
temp = x
x = y
y = temp

But in Python, it can be efficiently achieved with one line of code:

x, y = y, x
  • This concise method leverages tuple unpacking, where the right-hand side tuple values are assigned to the variables on the left-hand side. This works seamlessly for swapping two values without requiring a third variable.

  • Similarly, you can assign multiple variables in a single line:

a, b, c = 1, 2, 3  # Equivalent to (1, 2, 3)

Sets in Python

  • Sets are excellent for removing duplicate elements in a list. Using a set, duplicates are eliminated.

setNo = set([1, 1, 2, 4, 5])
  • Methods like .add() and .remove() are used to manage sets, and they are represented with curly braces {}.

Set Operations

Sets support various mathematical operations:

  • Union (|): Combines unique elements from both sets.

  • Intersection (&): Retrieves common elements present in both sets.

  • Difference (-): Retrieves elements in the first set but not in the second.

  • Symmetric Difference (^): Retrieves unique elements in both sets.

first = set(range(1, 6))
second = {3, 5, 6, 6, 8, 9, 4, 4, 3}

print(first | second)  # Union
print(first & second)  # Intersection
print(first - second)  # Difference
print(first ^ second)  # Symmetric Difference
  • Sets are unordered collections of unique items and do not allow duplicates. They do not support indexing.

Dictionary Operations

Dictionaries can be declared with named keys and values:

point = dict(x=1, y=2)
  • The index in dictionaries is the key, not sequential like 0, 1, 2 in lists. If the key doesn't exist, an error occurs. To prevent errors, use the .get() method:

print(point.get("a", 0))  # Outputs 0 if the key "a" doesn't exist

To delete a key:

del point["x"]
  • This removes the key-value pair associated with the key "x".

Dictionary Iteration

In a loop or iteration over a dictionary, it returns the keys of the dictionary.

We can iterate through a dictionary using:

my_dict = {'a': 1, 'b': 2, 'c': 3}

# Iterating through keys
for key in my_dict:
    value = my_dict[key]
    print(f"Key: {key}, Value: {value}")

# Iterating through dictionary items (as tuples)
for key, value in my_dict.items():
    print(f"Key: {key}, Value: {value}")
  • The dict.items() method provides an iterator that yields tuples of key-value pairs during iteration. Each iteration in the loop will have a tuple containing the key and its corresponding value.

Comprehensions in Python

Similar to list comprehensions, dictionaries can also be created using comprehension expressions.

For example:

# List Comprehension
values = [x * 2 for x in range(5)]  # Generates even numbers in a list

# Dictionary Comprehension
value_dict = {x: x * 2 for x in range(5)}  # Generates a dictionary with keys and their respective values

print(value_dict)

for key, value in value_dict.items():
    print(f"{key} => {value}")
  • When using comprehension expressions with () brackets, it creates a generator object. Generators are beneficial when dealing with large datasets as they consume less memory. They generate new values each time they are iterated but do not store them. The getsizeof function from the sys module can be used to determine the memory size of an object.

Generators

from sys import getsizeof

# Generator Expression
gen = (x * 2 for x in range(200))
print("Generator:", getsizeof(gen))

# List Comprehension
value = [x * 2 for x in range(200)]
print("List:", getsizeof(value))
  • Generators are more memory-efficient compared to lists. Generators do not hold all the values in memory at once; they generate values dynamically, consuming less memory. Hence, they do not have a len() method as they are not storing the entire sequence in memory. On the other hand, lists hold all the generated values in memory, and therefore, they do have a len() method to determine the length of the sequence.

Unpacking Operator

When printing a list, it typically shows as a sequence enclosed in square brackets: [item1, item2, item3]. To print the individual items separately, use the unpacking operator *.

For example:

numbers = [1, 2, 3, 4]
print(*numbers)  # Unpacks the list and prints individual items: 1 2 3 4
  • The unpacking operator * can be used with any iterable, including strings or numbers. It allows combining multiple iterables into a new one:

value = [*range(5), *"HelloWorld"]  # Combining range and string iterables
  • For dictionaries, the double asterisk ** can be used. When combining dictionaries with the same keys, the value from the second dictionary overrides the value from the first dictionary:

first = {'a': 1, 'b': 2}
second = {'b': 3, 'c': 4}
combined = {**first, **second}  # Merging two dictionaries

Expections and Try

  • Handling exceptions using try-except blocks:

try:
    # Your code that may raise an exception
except ValueError as ex:
    print("Lovely message:", ex)  # Print a message if a ValueError occurs
    print(type(ex))  # Print the type of the exception

# Adding an `else` clause to execute code when no exception occurs
else:
    # Code to execute if no exception occurs in the `try` block

Format Specifiers in Python's f-strings

In Python's f-strings, various format specifiers can be used to format different types of values. Here are some common format specifiers and their uses:

Integer Formatting:

  • :d - Formats an integer as a decimal number.

  • :b - Formats an integer as a binary number.

  • :o - Formats an integer as an octal number.

  • :x or :X - Formats an integer as a hexadecimal number (lowercase or uppercase).

Example:

number = 42
print(f"Decimal: {number:d}, Binary: {number:b}, Octal: {number:o}, Hex: {number:x}")
# Output: Decimal: 42, Binary: 101010, Octal: 52, Hex: 2a

Floating-Point Formatting:

  • :f - Formats a floating-point number as a decimal number.

  • :.nf - Formats a floating-point number with 'n' decimal places.

Example:

value = 3.14159
print(f"Float: {value:f}, Formatted Float: {value:.2f}")
# Output: Float: 3.141590, Formatted Float: 3.14

String Formatting:

  • :s - Formats a value as a string.

Example:

name = "Alice"
age = 30
print(f"Name: {name:s}, Age: {age:d}")
# Output: Name: Alice, Age: 30

Padding and Alignment:

  • :< - Left-aligns the text.

  • :> - Right-aligns the text.

  • :^ - Centers the text.

  • :<n, :>n, :^n - Aligns to a specified width 'n'.

Example:

text = "Hello"
print(f"Left-aligned: {text:<10}, Right-aligned: {text:>10}, Centered: {text:^10}")
# Output: Left-aligned: Hello     , Right-aligned:      Hello, Centered:   Hello

Last updated

Was this helpful?