0% found this document useful (0 votes)
10 views20 pages

Python Programming-Unit 4

Uploaded by

tejak700
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views20 pages

Python Programming-Unit 4

Uploaded by

tejak700
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 20

UNIT – IV

 Functions:
 Creating a Function
In Python a function is defined using the def keyword:
Example
def my_function():
print("Hello from a function")

 Calling a Function
To call a function, use the function name followed by parenthesis:
Example
def my_function():
print("Hello from a function")
my_function()

 Arguments
Information can be passed into functions as arguments.
Arguments are specified after the function name, inside the parentheses. You can add as many
arguments as you want, just separate them with a comma.
The following example has a function with one argument (fname). When the function is called, we
pass along a first name, which is used inside the function to print the full name:
Example
def my_function(fname):
print(fname + " Refsnes")

my_function("Emil")
my_function("Tobias")
my_function("Linus")

 Parameters or Arguments?
The terms parameter and argument can be used for the same thing: information that are passed into a
function.
 From a function's perspective:
A parameter is the variable listed inside the parentheses in the function definition.
An argument is the value that is sent to the function when it is called.

 Number of Arguments
By default, a function must be called with the correct number of arguments. Meaning that if your
function expects 2 arguments, you have to call the function with 2 arguments, not more, and not less.
Example
This function expects 2 arguments, and gets 2 arguments:
def my_function(fname, lname):
print(fname + " " + lname)

my_function("Emil", "Refsnes")
 Arbitrary Arguments, *args
If you do not know how many arguments that will be passed into your function, add a * before the
parameter name in the function definition.
This way the function will receive a tuple of arguments, and can access the items accordingly:

National Degree College, Nandyal Tasleem Group


Example
If the number of arguments is unknown, add a * before the parameter name:
def my_function(*kids):
print("The youngest child is " + kids[2])

my_function("Emil", "Tobias", "Linus")


 Passing a List as an Argument
You can send any data types of argument to a function (string, number, list, dictionary etc.), and it
will be treated as the same data type inside the function.
E.g. if you send a List as an argument, it will still be a List when it reaches the function:
Example
def my_function(food):
for x in food:
print(x)

fruits = ["apple", "banana", "cherry"]

my_function(fruits)
List
Lists are used to store multiple items in a single variable.
Lists are one of 4 built-in data types in Python used to store collections of data, the other 3 are Tuple,
Set, and Dictionary, all with different qualities and usage.
Lists are created using square brackets:
Example
Create a List:thislist = ["apple", "banana", "cherry"]
print(thislist)
 List Operations
1. Concatenation:
Concatenation involves combining two or more lists into a single new list. This operation appends
the elements of one list to the end of another.
2. Repetition:
Repetition involves creating a new list by repeating the elements of an existing list a specified
number of times.
3. Membership Testing:
Membership testing determines whether a specific element exists within a list. This is typically done
using the in and not in operators, which return a boolean value (True or False).

Here's a Python program demonstrating list operations:


# Define two lists
list1 = [1, 2, 3]
list2 = [4, 5, 6]

# Concatenation
concatenated_list = list1 + list2
print("Concatenated List:", concatenated_list)

# Repetition
repeated_list = list1 * 3
print("Repeated List:", repeated_list)

# Membership testing
print("Is 2 in list1?", 2 in list1)

National Degree College, Nandyal Tasleem Group


print("Is 7 in list1?", 7 in list1)

# You can also use 'not in' for membership testing


print("Is 7 not in list1?", 7 not in list1)
 List Methods:
append(element): Adds a single element to the end of the list.
insert(index, element): Inserts an element at a specified index within the list. The existing elements
from that index onwards are shifted to the right.
remove(element): Removes the first occurrence of the specified element from the list. If the element
is not found, a ValueError is raised
pop(index=-1): Removes and returns the element at the specified index. If no index is provided, it
removes and returns the last element of the list.
sort(key=None, reverse=False): Sorts the items of the list in place. By default, it sorts in ascending
order. The reverse=True argument can be used to sort in descending order. The key argument can be
used to specify a function to be called on each list element prior to making comparisons.
reverse(): Reverses the order of the elements in the list in place.

Example
# Define a list
my_list = [4, 2, 9, 6, 1]

# Append an element
my_list.append(7)
print("After append(7):", my_list)

# Insert an element at a specific index


my_list.insert(2, 8)
print("After insert(2, 8):", my_list)

# Remove the first occurrence of an element


my_list.remove(9)
print("After remove(9):", my_list)

# Pop an element from the list (by default, the last element)
popped_element = my_list.pop()
print("Popped element:", popped_element)
print("After pop():", my_list)

# Pop an element at a specific index


popped_element = my_list.pop(2)
print("Popped element at index 2:", popped_element)
print("After pop(2):", my_list)

# Sort the list in ascending order


my_list.sort()
print("After sort():", my_list)

# Reverse the list


my_list.reverse()
print("After reverse():", my_list)
 List Slices:
To extract a sublist in

National Degree College, Nandyal Tasleem Group


Python, you use the slice notation [start:end:step]. All three arguments are optional, with default values
that cover a wide range of common use cases. Slicing does not alter the original list; it returns a new
list containing the extracted elements.
 Syntax and parameters
The syntax for list slicing is list_name[start:end:step].
 start: The index where the slice begins (inclusive), defaulting to 0 if omitted.
 end: The index where the slice ends (exclusive), defaulting to the end of the list if omitted.
 step: The interval between elements, defaulting to 1 if omitted.
Examples
Let's use my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] for these examples.
 my_list[2:7] extracts elements from index 2 up to (but not including) index 7, resulting in ['c', 'd',
'e', 'f', 'g'].
 my_list[:5] extracts elements from the beginning up to index 5 (exclusive), resulting in ['a', 'b', 'c',
'd', 'e'].
 my_list[5:] extracts elements from index 5 to the end, resulting in ['f', 'g', 'h', 'i', 'j'].
 my_list[:] creates a shallow copy of the entire list.
 my_list[::2] extracts every other element, resulting in ['a', 'c', 'e', 'g', 'i'].
 my_list[1::3] extracts every third element starting from index 1, resulting in ['b', 'e', 'h'].

 Negative indices and steps


Negative indices count from the end of the list, with -1 being the last element.
 my_list[-4:] gets the last four elements, resulting in ['g', 'h', 'i', 'j'].
 my_list[:-2] gets all but the last two elements, resulting in ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'].
 my_list[::-1] reverses the entire list, resulting in ['j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a'] .
 my_list[Link]-1] reverses a sublist from index 6 to 1 (exclusive), resulting in ['g', 'f', 'e', 'd', 'c'].

Here's a Python program demonstrating list slicing:


# Define a list
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Extracting sublist using slicing [start:end]


print("Sublist from index 2 to 5:", my_list[2:6]) # [3, 4, 5, 6]

# Extractingsublist using slicing [start:]


print("Sublist from index 4 to end:", my_list[4:]) # [5, 6, 7, 8, 9]

# Extracting sublist using slicing [:end]


print("Sublist from start to index 4:", my_list[:5]) # [1, 2, 3, 4, 5]

# Extractingsublist using slicing [:]


print("Copy of the entire list:", my_list[:]) # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Extracting sublist using slicing [start:end:step]


print("Sublist with step 2:", my_list[Link]) # [2, 4, 6, 8]

# Extracting sublist using slicing [::step]


print("Every other element:", my_list[::2]) # [1, 3, 5, 7, 9]
print("Every other element in reverse:", my_list[::-2]) # [9, 7, 5, 3, 1]

# Reversing the list using slicing


print("Reversed list:", my_list[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1]
 List Loop:

National Degree College, Nandyal Tasleem Group


Traversing a list involves accessing each element within it. In Python, this can be achieved using
both for loops and while loops.
1. Using a for loop:
The for loop is typically used when you need to iterate over a sequence of items, such as a list, and
perform an action for each item.
Explanation:
 The first example directly iterates through each item in my_list. This is the most common and
Pythonic way to traverse a list when you only need the elements themselves.
 The second example uses range(len(my_list)) to generate a sequence of indices, allowing you to
access elements by their position using my_list[i]. This is useful when you need to know the
index of an element or modify the list in place.
2. Using a while loop:
The while loop repeatedly executes a block of code as long as a given condition is true. When
traversing a list with a while loop, you typically use an index to keep track of the current position.
Explanation:
 An index variable is initialized to 0.
 The while loop continues as long as index is less than the length of my_list.
 Inside the loop, the element at the current index is printed.
 index is incremented by 1 in each iteration to move to the next element.

Here's a Python program demonstrating list traversal using both for and while loops:
# Define a list
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Traversing the list using for loop


print("Traversing the list using for loop:")
for element in my_list:
print(element, end=" ")
print()

# Traversing the list using for loop with index


print("Traversing the list using for loop with index:")
for index, element in enumerate(my_list):
print(f"Index: {index}, Element: {element}")

# Traversing the list using while loop


print("Traversing the list using while loop:")
index = 0
while index <len(my_list):
print(my_list[index], end=" ")
index += 1
print()

# Traversing the list in reverse order using for loop


print("Traversing the list in reverse order using for loop:")
for element in reversed(my_list):
print(element, end=" ")
print()

# Traversing the list in reverse order using while loop


print("Traversing the list in reverse order using while loop:")
index = len(my_list) - 1
while index >= 0:

National Degree College, Nandyal Tasleem Group


print(my_list[index], end=" ")
index -= 1
print()
 Mutability:
In Python, a list is a mutable data type, meaning its contents can be changed, added to, or removed
from after it has been created. This is a core feature that distinguishes it from immutable types, like
strings or tuples, where any operation that seems to alter the object actually creates a new one.
This mutability offers great flexibility for handling dynamic collections of data. A list's identity (its
memory address) remains the same even as its contents change.
 Methods for modifying a list
You can change a list's elements in several ways:
Item assignment: Use the index operator ([]) on the left side of an assignment to change a single
element's value.
Slicing: Replace a range of elements with a new list using the slice operator ([:]).
append(): Add a single element to the end of the list.
extend(): Add all elements from another list to the end of the current list.
remove(): Remove the first occurrence of a specific value.
pop(): Remove and return an element at a specific index.
 Implications of list mutability
The mutable nature of lists can have significant consequences, especially when assigning one list
variable to another.
 Aliasing: When you assign a list to a new variable, you are not creating a copy. You are
creating a new reference to the same list object in memory.
 Creating a copy: To avoid this, you must explicitly create a copy of the list. One common
way is by using the slice operator [:].Understanding list mutability is fundamental for writing
reliable and predictable Python code, especially when passing lists as arguments to functions
or working with shared data.

Here's an example demonstrating the mutability of lists in Python:
# Define a list
my_list = [1, 2, 3, 4, 5]

# Print the original list


print("Original List:", my_list)

# Modify an element
my_list[2] = 10
print("List after modifying an element:", my_list)

# Add an element
my_list.append(6)
print("List after adding an element:", my_list)

# Remove an element
my_list.remove(4)
print("List after removing an element:", my_list)
 Aliasing:
Aliasing in programming, particularly with mutable objects like Python lists, occurs when multiple
variables refer to the same object in memory. This means that instead of creating a separate copy of
the object, a new variable is assigned to point to the exact same memory location as an existing
variable.

National Degree College, Nandyal Tasleem Group


Key characteristics of aliasing with lists:
 Shared Reference:
When you assign one list variable to another (e.g., list2 = list1), you are not creating a new list
object. Instead, both list1 and list2 now store a reference to the identical list object in memory.
 Mutual Modification:
Because both variables point to the same object, any modification made to the list through
one variable will be reflected when accessing the list through the other variable. This is a
significant point of difference from simply assigning values of immutable objects like
integers or strings.
 Potential for Unexpected Behavior:
This shared modification can lead to unexpected behavior if not understood. If you intend to
have two independent lists, aliasing will cause unintended side effects.
Distinction from Cloning:
If independent copies of lists are required, cloning or copying mechanisms must be employed. For
example, using slicing (list2 = list1[:]) or the copy() method (list2 = [Link]()) creates a new list object
with the same elements, preventing aliasing.

Here's an example demonstrating aliasing in Python:


# Define a list
original_list = [1, 2, 3, 4, 5]

# Create an alias for the original list


alias_list = original_list

# Print both lists


print("Original List:", original_list)
print("Alias List:", alias_list)

# Modify the alias list


alias_list[2] = 10
alias_list.append(6)

# Print both lists again


print("Original List after modification:", original_list)
print("Alias List after modification:", alias_list)
 Cloning Lists:
Cloning a list in Python involves creating a new list that contains the same elements as an existing
list, but is independent of the original. This means that modifications to the cloned list will not affect
the original list, and vice-versa. Two common methods for achieving this are using slicing or the list()
constructor.
 Cloning using Slicing
Slicing allows you to create a shallow copy of a list by extracting all elements into a new list.
 Cloning using list()
The built-in list() constructor can also be used to create a shallow copy of an existing list.
 Shallow vs. Deep Copies
Both slicing and list() create shallow copies. This means that if the original list contains mutable
objects (like other lists), the copied list will contain references to those same mutable objects. If you
modify a mutable object within the cloned list, it will also affect the original list. For independent
copies of nested mutable objects, a deep copy using the [Link]() function from the copy module
is required.

Here's an example demonstrating cloning lists in Python:

National Degree College, Nandyal Tasleem Group


# Define a list
original_list = [1, 2, 3, 4, 5]

# Clone the list using slicing


cloned_list_slicing = original_list[:]

# Clone the list using list()


cloned_list_list_func = list(original_list)

# Print all lists


print("Original List:", original_list)
print("Cloned List (Slicing):", cloned_list_slicing)
print("Cloned List (list()):", cloned_list_list_func)

# Modify the original list


original_list[2] = 10
original_list.append(6)

# Print all lists again


print("Original List after modification:", original_list)
print("Cloned List (Slicing) after modification:", cloned_list_slicing)
print("Cloned List (list()) after modification:", cloned_list_list_func)
List Parameters:
When a list is passed as a parameter to a function in Python, the function receives a reference to the
original list object, not a copy of it. This means that if the function modifies the list, those changes
will be reflected in the original list outside the function. This behavior is a direct consequence of lists
being mutable data types in Python.
Effects of Mutability when Passing Lists to Functions:
 Direct Modification: Any in-place modification within the function, such as appending
elements, removing elements, or changing element values by index, will directly alter the
original list.
 Aliasing:
The parameter inside the function acts as an alias for the original list. Both the original
variable and the function parameter refer to the same object in memory.
 Potential for Unintended Side Effects:
If a function modifies a list passed to it without the caller's expectation, it can lead to
difficult-to-debug issues. This is a common pitfall when working with mutable objects.
Mitigating Unintended Side Effects:
 Pass a Copy: If the function should not modify the original list, pass a copy of the list
instead. This can be done using slicing (my_list[:]), the list() constructor (list(my_list)), or the copy
module ([Link](my_list) for shallow copies or [Link](my_list) for deep copies of nested
structures).
Return a New List: Design the function to return a new list with the desired modifications, leaving
the original list untouched. This promotes functional programming principles and pure
[Link] list mutability and its implications when passing lists to functions is crucial
for writing correct and predictable Python code.

Here's an example demonstrating passing lists to functions and the effects of


mutability:
# Define a function that modifies a list
defmodify_list(my_list):
my_list.append(6)
my_list[2] = 10

National Degree College, Nandyal Tasleem Group


print("List inside function:", my_list)

# Define a function that reassigns a list


defreassign_list(my_list):
my_list = [7, 8, 9]
print("List inside reassign function:", my_list)

# Define a list
original_list = [1, 2, 3, 4, 5]

# Pass the list to the modify function


print("Original List before modification:", original_list)
modify_list(original_list)
print("Original List after modification:", original_list)

# Pass the list to the reassign function


print("Original List before reassignment:", original_list)
reassign_list(original_list)
print("Original List after reassignment:", original_list)
 Tuple
Tuples are used to store multiple items in a single variable.
Tuple is one of 4 built-in data types in Python used to store collections of data, the other 3 are List,
Set, and Dictionary, all with different qualities and usage.
A tuple is a collection which is ordered and unchangeable.
Tuples are written with round brackets.
Example Get your own Python Server
Create a Tuple:
thistuple = ("apple", "banana", "cherry")
print(thistuple)
Tuple Assignment:
Tuple assignment in Python is a powerful feature that allows for assigning multiple values to
multiple variables in a single line of code. This is also known as tuple unpacking or multiple
assignment.
Mechanism:
 Right-hand side: A tuple or any iterable (like a list) on the right side of the assignment
statement provides the values.
 Left-hand side: A tuple of variables on the left side receives these values.

 Assignment: Each value from the right-hand side is assigned to its corresponding variable on
the left-hand side based on their positional order.

Key Characteristics:
 Matching Lengths:

The number of variables on the left side must exactly match the number of elements in the
tuple/iterable on the right side. If the lengths do not match, a ValueError will be raised (e.g.,
"too many values to unpack" or "not enough values to unpack").

 Parentheses Optional:

National Degree College, Nandyal Tasleem Group


While the concept is "tuple assignment," parentheses are often optional around the variables
on the left and the values on the right, as long as the elements are separated by commas.
Python interprets comma-separated values as a tuple by default

Basic tuple assignment


x, y = 1, 2
print("x:", x) # Output: 1
print("y:", y) # Output: 2

# Swapping values
x, y = y, x
print("x:", x) # Output: 2
print("y:", y) # Output: 1

# Assigning values from a tuple


point = (3, 4)
x, y = point
print("x:", x) # Output: 3
print("y:", y) # Output: 4
Tuple as Return Value:
How Tuples are Used as Return Values:
 Returning Multiple Pieces of Data: When a function needs to compute and return several
distinct but related values, packaging them into a tuple provides a clean and organized way to
do so.

Unpacking the Returned Tuple: The caller of the function can then unpack the returned tuple into
individual variables, making it easy to access each [Link] Tuple Creation (Optional
but Recommended for Clarity): While Python often implicitly creates a tuple when multiple values
are returned separated by commas, explicitly enclosing them in parentheses can enhance readability,
especially for empty tuples or to avoid [Link]
antages of Using Tuples as Return Values:
 Simplicity:It provides a straightforward way to return multiple values without needing to
create custom classes or data structures for simple cases.
 Readability:When unpacked, the individual variables clearly represent the different
components of the returned data.
 Efficiency:For returning a small, fixed number of related values, tuples are generally more
lightweight than creating dedicated classes.
Considerations:
 For a large number of returned values, or if the returned data has complex relationships and
behavior, defining a custom class or dataclass might offer better organization and
maintainability.
 The order of values in the tuple is crucial, as unpacking relies on this order.
# Define a function that returns a tuple
defget_point():
x=1
y=2
return x, y

# Call the function and unpack the returned tuple


point = get_point()
National Degree College, Nandyal Tasleem Group
print("Returned tuple:", point)

# Unpack the tuple into separate variables


x, y = get_point()
print("x:", x)
print("y:", y)

# Define a function that returns multiple values with different data types
defget_student_info():
name = "John"
age = 20
grades = [90, 85, 95]
return name, age, grades

# Call the function and unpack the returned tuple


name, age, grades = get_student_info()
print("Name:", name)
print("Age:", age)
print("Grades:", grades)

Dictionary Operations:
To perform dictionary operations like creation, insertion, deletion, and updating, you can use
Python's curly braces
{} or the dict() constructor for creation, the dictionary[key] = value assignment for insertion/updating, the
del statement or the .pop() method for deletion, and the update() method to add multiple key-value
pairs.
1. Creation
 Using curly braces: The most common way is to use curly braces {} with key-value pairs
separated by colons, with pairs separated by commas.

Using dict() constructor: You can also use the dict() function, for example, by passing keyword
arguments
2. Insertion
 Using the assignment operator (=): This adds a new key-value pair or updates the value if the
key already exists

3. Updating Values
 Using the assignment operator (=): To update an existing value, simply assign a new value to
the existing key

National Degree College, Nandyal Tasleem Group


Using the update() method: This method adds key-value pairs from another dictionary or an iterable of
key-value pairs
4. Deletion
 Using the del keyword: This removes a key-value pair by specifying the key.

Using the .pop() method: This removes a key-value pair and returns its value.
Using the .clear() method: This removes all key-value pairs, effectively emptying the dictionary

Here's an example demonstrating dictionary operations in Python:


# Create a dictionary
person = {"name": "John", "age": 30}
print("Original dictionary:", person)

# Insert a new key-value pair


person["city"] = "New York"
print("After insertion:", person)

# Update an existing value


person["age"] = 31
print("After update:", person)

# Delete a key-value pair


del person["age"]
print("After deletion:", person)

# Use the pop() method to delete a key-value pair


city = [Link]("city")
print("Popped value:", city)
print("After pop:", person)

# Use the update() method to add multiple key-value pairs


[Link]({"age": 32, "country": "USA"})
print("After update:", person)

# Use the get() method to retrieve a value


name = [Link]("name")

National Degree College, Nandyal Tasleem Group


print("Name:", name)

# Use the keys(), values(), and items() methods


print("Keys:", list([Link]()))
print("Values:", list([Link]()))
print("Items:", list([Link]()))

 Dictionary Methods:
keys(): This method returns a view object that displays a list of all the keys in the dictionary in the order of
insertion.
values(): This method returns a view object that displays a list of all the values in the dictionary in the order
of insertion.
items(): This method returns a view object that displays a list of all the key-value pairs in the dictionary as
tuples, in the order of insertion.
get(key, default_value=None): This method returns the value for the specified key. If the key is not found,
it returns the default_value (which defaults to None if not provided), instead of raising a KeyError.
update(other_dict_or_iterable): This method updates the dictionary with elements from another
dictionary or an iterable of key-value pairs. If a key already exists, its value is updated; otherwise, new key-
value pairs are added.
pop(key, default_value=None): This method removes the item with the specified key and returns its value.
If the key is not found and default_value is provided, it returns default_value; otherwise, it raises a KeyError.

Here's an example demonstrating dictionary methods in Python:


# Create a dictionary
person = {"name": "John", "age": 30, "city": "New York"}

# keys() method
print("Keys:", list([Link]()))

# values() method
print("Values:", list([Link]()))

# items() method
print("Items:", list([Link]()))

# get() method
name = [Link]("name")
print("Name:", name)

# get() method with default value


National Degree College, Nandyal Tasleem Group
country = [Link]("country", "USA")
print("Country:", country)

# update() method
[Link]({"age": 31, "country": "USA"})
print("Updated dictionary:", person)

# pop() method
city = [Link]("city")
print("Popped value:", city)
print("Dictionary after pop:", person)

Advanced List Processing:


Advanced list processing involves efficient and Pythonic techniques beyond basic operations,
including
- List Comprehension: compact syntax for creating lists.
- Nested list comprehensions.
List Comprehension:
List comprehension in Python offers a concise and efficient way to create new lists based on existing
iterables (like lists, tuples, strings, or ranges). It provides a more compact and often more readable
alternative to traditional for loops for list creation and transformation.
The general syntax for list comprehension is:
Python
new_list = [expression for item in iterable if condition]
Components of List Comprehension:
 expression: This defines what value will be included in the new_list for each item that satisfies
the condition. It can be a direct value, a variable, or a calculation involving the item.
 item: This is a variable that takes on the value of each element in the iterable during the
iteration.
 iterable: This is the sequence (e.g., list, tuple, string, range) over which the comprehension
iterates.
 if condition (Optional): This is a filter that determines whether an item from the iterable
should be processed and included in the new_list. Only items for which the condition evaluates
to True will be considered.

Here's an example demonstrating list comprehension in Python:


# Create a list of squares using list comprehension
numbers = [1, 2, 3, 4, 5]
squares = [x**2 for x in numbers]
print("Squares:", squares)

# Create a list of even numbers using list comprehension

National Degree College, Nandyal Tasleem Group


even_numbers = [x for x in numbers if x % 2 == 0]
print("Even numbers:", even_numbers)

# Create a list of strings in uppercase using list comprehension


fruits = ["apple", "banana", "cherry"]
uppercase_fruits = [[Link]() for fruit in fruits]
print("Uppercase fruits:", uppercase_fruits)

# Create a list of tuples using list comprehension


coordinates = [(x, y) for x in range(3) for y in range(2)]
print("Coordinates:", coordinates)

# Create a list of dictionaries using list comprehension


people = [{"name": "John", "age": 30}, {"name": "Alice", "age": 25}]
names = [person["name"] for person in people]
print("Names:", names)

 Nested list comprehensions.


Nested list comprehensions in Python provide a concise way to create lists, especially when dealing
with lists of lists or when multiple iterations are required. They are essentially list comprehensions
within other list comprehensions, mirroring the structure of nested for loops.
 Basic Structure:
A nested list comprehension typically involves multiple for clauses. The order of these clauses in the
comprehension corresponds to the nesting order of for loops, with the leftmost for clause representing
the outermost loop and subsequent for clauses representing inner loops.
Ex:
[expression for item1 in iterable1 for item2 in iterable2 ... for itemN in iterableN if condition]
Common Use Cases:
 Flattening a List of Lists: This involves transforming a list containing sublists into a single, flat
list.

Generating a List of Lists (Matrix): Creating a multi-dimensional list, like a matrix.


Applying Operations to Nested Elements: Performing calculations or transformations on elements
within inner lists.
Conditional Filtering: Applying conditions to filter elements from nested structures.
Readability Considerations:
While nested list comprehensions offer conciseness, excessive nesting can sometimes reduce
readability. For very complex logic, using traditional nested for loops might be more understandable.
The choice between them often depends on the complexity of the operation and personal preference
for code clarity.

Here's an example demonstrating nested list comprehensions in Python:


# Create a 3x3 matrix using nested list comprehension

National Degree College, Nandyal Tasleem Group


matrix = [[x*y for x in range(1, 4)] for y in range(1, 4)]
print("Matrix:")
for row in matrix:
print(row)

# Create a list of pairs using nested list comprehension


numbers = [1, 2, 3]
pairs = [(x, y) for x in numbers for y in numbers]
print("Pairs:", pairs)

# Create a list of pairs with a condition using nested list comprehension


pairs_with_condition = [(x, y) for x in numbers for y in numbers if x != y]
print("Pairs with condition:", pairs_with_condition)

# Create a matrix with squares using nested list comprehension


squares_matrix = [[x**2 for x in range(1, 4)] for _ in range(3)]
print("Squares matrix:")
for row in squares_matrix:
print(row)

 Illustrative Programs:
- Selection Sort
- Insertion Sort
- Merge Sort
- Histogram
Selection Sort:
Selection Sort is a simple, in-place comparison-based sorting algorithm. It works by repeatedly
finding the minimum element from the unsorted part of the list and putting it at the beginning of the
sorted part.
Here's how Selection Sort works in Python:
 Iterate through the list: The algorithm iterates from the first element to the second-to-last
element. This outer loop marks the boundary between the sorted and unsorted portions of the
list.
 Find the minimum element: In each iteration of the outer loop, an inner loop iterates
through the unsorted portion of the list to find the index of the minimum element.
 Swap elements: Once the minimum element in the unsorted portion is found, it is swapped
with the element at the current position of the outer loop (the first element of the unsorted
portion). This effectively moves the minimum element to its correct sorted position.
 Repeat: This process repeats until the entire list is sorted.

National Degree College, Nandyal Tasleem Group


Selection Sort:
Selection Sort is a simple, in-place comparison-based sorting algorithm. It works by repeatedly
finding the minimum element from the unsorted part of the list and putting it at the beginning of the
sorted part.
Here's how Selection Sort works in Python:
 Iterate through the list: The algorithm iterates from the first element to the second-to-last
element. This outer loop marks the boundary between the sorted and unsorted portions of the
list.
 Find the minimum element: In each iteration of the outer loop, an inner loop iterates
through the unsorted portion of the list to find the index of the minimum element.
 Swap elements: Once the minimum element in the unsorted portion is found, it is swapped
with the element at the current position of the outer loop (the first element of the unsorted
portion). This effectively moves the minimum element to its correct sorted position.
 Repeat: This process repeats until the entire list is sorted.

Python Implementation:
def selection_sort(arr):
n = len(arr)
for i in range(n):
# Find the minimum element in the unsorted part
min_idx = i
for j in range(i + 1, n):
if arr[j] <arr[min_idx]:
min_idx = j

# Swap the found minimum element with the first element of the unsorted part
arr[i], arr[min_idx] = arr[min_idx], arr[i]
returnarr

# Example usage:
my_list = [64, 25, 12, 22, 11]
sorted_list = selection_sort(my_list)
print(f"Sorted list: {sorted_list}")

Insertion Sort:
Insertion Sort is a simple sorting algorithm that builds the final sorted array one item at a time. It is
significantly less efficient on large lists than more advanced algorithms like quicksort, heapsort, or
merge sort. However, it offers advantages for small data sets or partially sorted lists.

Here is the Python implementation of Insertion Sort:


def insertion_sort(arr):
"""

National Degree College, Nandyal Tasleem Group


Sorts an array using the Insertion Sort algorithm.

Args:
arr: The list to be sorted.
"""
n = len(arr)

# Traverse through 1 to len(arr)


for i in range(1, n):
key = arr[i] # Current element to be inserted
j=i-1 # Index of the last element in the sorted subarray

# Move elements of arr[0..i-1], that are greater than key,


# to one position ahead of their current position
while j >= 0 and key <arr[j]:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key # Place key at its correct position

# Example usage:
my_list = [12, 11, 13, 5, 6]
insertion_sort(my_list)
print("Sorted array is:", my_list)
Merge Sort:
Merge sort is an efficient, comparison-based, divide-and-conquer sorting algorithm. It works by
recursively dividing an array into two halves, sorting each half, and then merging the sorted halves
back together.

Here's an implementation of Merge Sort in Python:


defmerge_sort(arr):
iflen(arr) > 1:
mid = len(arr) // 2 # Find the middle of the array
left_half = arr[:mid] # Divide the array elements into two halves
right_half = arr[mid:]

merge_sort(left_half) # Sort the first half


merge_sort(right_half) # Sort the second half

i=j=k=0

National Degree College, Nandyal Tasleem Group


# Copy data to temporary arrays left_half[] and right_half[]
while i <len(left_half) and j <len(right_half):
ifleft_half[i] <right_half[j]:
arr[k] = left_half[i]
i += 1
else:
arr[k] = right_half[j]
j += 1
k += 1

# Check for any remaining elements in left_half


while i <len(left_half):
arr[k] = left_half[i]
i += 1
k += 1

# Check for any remaining elements in right_half


while j <len(right_half):
arr[k] = right_half[j]
j += 1
k += 1

# Example usage:
my_list = [12, 11, 13, 5, 6, 7]
merge_sort(my_list)
print("Sorted array is:", my_list)
Explanation:
o Base Case: If the length of the array (arr) is 1 or less, it is already sorted, so the
function returns.
o Divide: The array is divided into two halves: left_half and right_half.
o Conquer (Recursive Calls):merge_sort is called recursively on both left_half and
right_half to sort them independently.
o Merge: After the halves are sorted, the merge process begins.
 Three pointers i, j, and k are initialized to 0. i for left_half, j for right_half, and k
for the original arr.
 Elements from left_half and right_half are compared, and the smaller element is
placed into arr[k]. The corresponding pointer (i or j) and k are incremented.
 After one of the halves is exhausted, any remaining elements from the other
half are copied directly into arr.

This process ensures that the elements are merged in sorted order, ultimately resulting in a fully
sorted array.

Histogram:
A histogram in Python is a graphical representation used to visualize the distribution of numerical
data. It groups data into "bins" and displays the frequency or count of data points falling within each
bin as bars.
Creating a Histogram with Matplotlib:
The most common way to create a histogram in Python is using the [Link]() function.
[Link] as plt
importnumpy as np

National Degree College, Nandyal Tasleem Group


# Generate some sample data
data = [Link](1000) # 1000 random numbers from a standard normal distribution

# Create the histogram


[Link](data)

# Add labels and a title


[Link]("Value")
[Link]("Frequency")
[Link]("Histogram of Sample Data")

# Display the plot


[Link]()

Key Parameters of [Link]():


 x: The input data (a sequence of numerical values).
 bins: Defines the number or edges of the bins. It can be an integer (number of bins), a
sequence (bin edges), or "auto" for automatic bin selection.
 density: If True, the histogram values are normalized to form a probability density, such that
the integral over the range is 1. If False (default), the result is the number of samples in each
bin.
 color: Sets the color of the histogram bars.
 edgecolor: Sets the color of the bar edges.
 log: If True, the y-axis (frequency/density) will be on a logarithmic scale.

National Degree College, Nandyal Tasleem Group

You might also like