UNIT-2
FUNCTIONS & FILES
FUNCTIONS & FILES:Defining a Function, Passing Arguments, Return Values, Passing a
List, Creating and Using a Class, Strings: Working with Strings, String Methods, Files: Reading
from a File, Writing to a File, Exceptions, Python Libraries: Importing libraries.
What is a function?
A function is a reusable block of code that performs a specific task. Functions can take
inputs (called parameters) and optionally return an output.
Basic Syntax
def function_name(parameters):
"""
Optional docstring explaining what the function does.
"""
# Code block
return value # optional
• def → keyword used to define a function
• function_name → your chosen name for the function (should follow Python naming
rules)
• parameters → optional input values
• return → optional keyword to send a value back
Example
# File: my_functions.py
def greet(name):
"""This function greets a person by their name."""
message = f"Hello, {name}!"
return message
def add_numbers(a, b):
"""This function adds two numbers."""
return a + b
Using functions from a Python file
If you save the above as my_functions.py, you can use it in another file:
# File: [Link]
from my_functions import greet, add_numbers
print(greet("Alice")) # Output: Hello, Alice!
print(add_numbers(5, 7)) # Output: 12
Or import the entire module:
import my_functions
print(my_functions.greet("Bob")) # Output: Hello, Bob!
print(my_functions.add_numbers(3, 4)) # Output: 7
In Python, there are several ways to define a function depending on the style and purpose. Here’s
a clear breakdown:
1. Standard Function (Using def)
The most common way to define a function.
def add(a, b):
return a + b
2. Function with Default Parameters
You can give default values to parameters.
def greet(name="Guest"):
return f"Hello, {name}!"
3. Function with Variable-length Arguments
• *args → for any number of positional arguments
• **kwargs → for any number of keyword arguments
def sum_all(*args):
return sum(args)
def print_info(**kwargs):
for key, value in [Link]():
print(f"{key}: {value}")
4. Lambda Function (Anonymous Function)
A short, single-expression function.
square = lambda x: x**2
print(square(5)) # Output: 25
5. Nested Functions
A function defined inside another function.
def outer(x):
def inner(y):
return y * 2
return inner(x) + 1
print(outer(5)) # Output: 11
6. Recursive Functions
A function that calls itself.
def factorial(n):
if n == 0:
return 1
return n * factorial(n-1)
print(factorial(5)) # Output: 120
PASSING ARGUMENTS
In Python, information is passed to functions via arguments during a function call,
which correspond to variables defined as parameters in the function signature.
The primary methods for passing parameters offer flexibility in how functions are
defined and called.
Types of Parameter Passing
Python supports several ways to pass arguments to a function:
• Positional Arguments: Arguments are passed based on their order.
The first argument in the call is assigned to the first parameter in the
definition, and so on. The order matters significantly.
python
def greet(name, message):
print(f"{message}, {name}!")
greet("Alice", "Hello") # Output: Hello, Alice!
• Keyword Arguments: Arguments are passed using their parameter names, allowing the order to
be changed.
This improves code readability.
python
def greet(name, message):
print(f"{message}, {name}!")
# Order doesn't matter when using keywords
greet(message="Good morning", name="Bob") # Output: Good morning, Bob!
• Default Arguments: Parameters can be assigned default values in the function definition,
making them optional during the function call.
If a value isn't provided, the default is used.
python
def greet(name, message="Hello"):
print(f"{message}, {name}!")
greet("Charlie") # Output: Hello, Charlie!
greet("David", "Goodbye") # Output: Goodbye, David!
• **Variable-Length Arguments (*args and kwargs):
o *args allows a function to accept any number of non-keyword (positional) arguments, which are
collected into a tuple inside the function.
o **kwargs allows a function to accept any number of keyword arguments, which are collected
into a dictionary inside the function.
python
def calculate_sum(*args):
return sum(args)
print(calculate_sum(1, 2, 3, 4)) # Output: 10
Use code with caution.
Python's Passing Mechanism: "Call by Object Reference"
Python uses a mechanism best described as "call by object reference" or "pass
by assignment," rather than strict "pass by value" or "pass by reference" as seen in other
languages.
When an argument is passed, a reference to the actual object is passed to the
function.
• Mutable objects (like lists, dictionaries, sets) can be modified in-place within the function, and
these changes will affect the original object outside the function.
• Immutable objects (like integers, strings, tuples) cannot be changed in-place.
If you try to modify an immutable parameter inside the function, a new local object
is created, and the original object outside the function remains unchanged.
In Python, values are returned from functions using the return statement, which
allows a function to send a result back to its caller.
To use these values with files, you typically call the function and then use file-
handling methods like write() to save the returned data.
RETURN VALUES
The return statement immediately terminates the function's execution and sends a
value back to the caller.
• Basic Syntax: Use return followed by the value or expression to be returned.
python
def multiply(a, b):
result = a * b
return result
my_product = multiply(4, 5)
print(my_product) # Output: 20
• Returning Multiple Values: Python functions can return multiple values, which are
automatically packed into a tuple.
python
def get_user_info():
return "John Doe", "[Link]@[Link]"
name, email = get_user_info()
print(f"Name: {name}, Email: {email}")
Use code with caution.
• Implicit None Return: If a function lacks a return statement or uses return without a value, it
implicitly returns None.
Using Returned Values in File Operations
To save a function's returned value to a file, capture the value and use file I/O.
The open() function provides a file object with methods like write() and read().
python
def process_data(data_list):
processed_output = ", ".join(map(str, data_list))
return processed_output
data_to_write = process_data([10, 20, 30, 40])
file_path = 'output_data.txt'
with open(file_path, 'w') as f:
[Link](data_to_write) # write() returns the number of characters written
with open(file_path, 'r') as f:
content = [Link]() # read() returns the file's content as a string
print(f"Content read from file: {content}")
In Python, you can pass a list to a function as a regular argument, and handle lists of
file names in file operations by iterating through them.
Lists are mutable objects, so changes within a function affect the original list.
Passing a List
In Python, you pass a list to a function just like any other argument, by including its
name in the function call.
Python uses a mechanism often described as "pass-by-object-reference," which means
that modifications to the list inside the function will affect the original list.
Basic Example
Here is how you define a function that accepts a list and then pass a list to it:
python
def process_list(my_list_param):
"""Prints each item in the list."""
for item in my_list_param:
print(item)
fruits = ["apple", "banana", "cherry"]
process_list(fruits)
Output:
apple
banana
cherry
In this case, my_list_param inside the function is a reference (or an alias) to the
same list object that fruits refers to outside the function.
Modifying the List (Pass-by-Reference)
Because lists are mutable (changeable), methods like append(), extend(), or sort() used
inside the function will modify the original list.
python
def add_item(my_list_param, item):
"""Appends an item to the list in-place."""
my_list_param.append(item)
scores = [10, 20, 30]
add_item(scores, 40)
print(scores)
Output:
[10, 20, 30, 40]
The original scores list is permanently modified.
Passing a Copy (Preventing Modification)
If you want the function to work with the list's data without changing the original,
you must pass a copy of the list.
You can create a shallow copy using the slice operator [:] or the list() constructor.
python
def add_item_to_copy(my_list_param, item):
"""Modifies a copy, leaving the original list unchanged."""
t = list(my_list_param) # or t = my_list_param[:]
[Link](item)
return t # often best practice to return the new list
original_scores = [10, 20, 30]
new_scores = add_item_to_copy(original_scores, 40)
print(f"Original list: {original_scores}")
print(f"New list: {new_scores}")
Output:
Original list: [10, 20, 30]
New list: [10, 20, 30, 40]
Unpacking a List as Multiple Arguments
If you have a function that expects multiple separate arguments, you can unpack
the elements of a list into those arguments using the * operator during the function call.
python
def display_scores(score1, score2, score3):
print(f"S1: {score1}, S2: {score2}, S3: {score3}")
scores_list = [85, 92, 78]
display_scores(*scores_list)
Use code with caution.
Output:
S1: 85, S2: 92, S3: 78
CREATING & USING A CLASS
CREATING A CLASS
You define a class using the class keyword followed by the class name
(conventionally capitalized using CamelCase) and a colon.
Key Components:
• class keyword: Declares a new class.
• Docstrings: A string literal used to document the class's purpose (optional but recommended).
• __init__ method (Constructor): A special method that runs automatically whenever a new
object (instance) is created. It is used to initialize the object's attributes with specific values.
• self parameter: The first parameter of any instance method, which refers to the current instance
of the class itself. Python passes this argument automatically, but you must include it in the
method definition.
• Attributes: Variables defined within a class.
o Instance attributes: Unique to each object (defined within __init__ using self.attribute_name).
o Class attributes: Shared by all instances of the class (defined directly within the class body,
outside any method).
• Methods: Functions defined inside a class that describe the object's behaviors.
python
class Dog:
# Class attribute (shared by all instances)
species = "Canis familiaris"
# The __init__ method initializes instance attributes
def __init__(self, name, age):
"""Initializes the dog with a name and age."""
[Link] = name # Instance attribute
[Link] = age # Instance attribute
# An instance method (a function within the class)
def bark(self):
"""Makes the dog bark."""
return f"{[Link]} says Woof!"
# Another method
def describe(self):
"""Provides a description of the dog."""
return f"{[Link]} is a {[Link]} year old {[Link]}."
Using a Class (Creating Objects)
To use a class, you create an instance (an object) by calling the class name as if it
were a function, passing any arguments required by the __init__ method. This process is called
instantiation.
python
# Create two instances (objects) of the Dog class
dog1 = Dog("Buddy", 3)
dog2 = Dog("Lucy", 5)
Use code with caution.
Accessing Attributes and Methods
You access an object's attributes and call its methods using the dot (.) operator.
python
# Access instance attributes
print(f"{[Link]} is {[Link]} years old.")
# Output: Buddy is 3 years old.
# Access class attributes (can be accessed via the class or an object)
print(f"Buddy's species: {[Link]}")
# Output: Buddy's species: Canis familiaris
# Call instance methods
print([Link]())
# Output: Lucy says Woof!
print([Link]())
# Output: Buddy is a 3 year old Canis familiaris.
Modifying Attributes
You can change the values of instance attributes at any time using the dot operator
and assignment.
python
[Link] = 4
print(f"{[Link]} is now {[Link]} years old.")
# Output: Buddy is now 4 years old.
STRINGS
In Python, strings are immutable sequences of Unicode characters used for handling
text data.
Working with strings involves various operations like indexing, slicing,
concatenation, and formatting.
String methods are built-in functions that perform specific operations on string
objects and return a new string, as the original string cannot be modified (immutability).
Working with Strings
• Creation: Strings are created by enclosing characters in single ('...'), double ("..."), or triple
quotes ("""...""" for multiline strings).
• Indexing and Slicing: You can access individual characters using zero-based indexing
(string[0]) or extract a portion (substring) using slicing (string[start:end]).
• Concatenation & Repetition:
o The + operator joins two or more strings ("Hello" + " World").
o The * operator repeats a string a specified number of times ("ha" * 3 results in "hahaha").
• Immutability: A key concept is that strings are immutable.
Any method that appears to change a string actually creates and returns a new
string with the modifications.
Python offers a rich set of built-in methods for manipulating strings.
These methods are invoked directly on string objects and return new strings, as
strings in Python are immutable.
Common String Methods:
• Case Conversion:
• lower(): Converts all characters to lowercase.
• upper(): Converts all characters to uppercase.
• capitalize(): Capitalizes the first character of the string.
• title(): Capitalizes the first character of each word.
• swapcase(): Swaps the case of all characters (uppercase to lowercase, and vice-versa).
• Whitespace and Character Removal:
• strip(): Removes leading and trailing whitespace.
• lstrip(): Removes leading whitespace.
• rstrip(): Removes trailing whitespace.
• removeprefix(prefix): Removes a specified prefix if present.
• removesuffix(suffix): Removes a specified suffix if present.
• Searching and Replacing:
• find(substring): Returns the lowest index of the first occurrence of the substring, or -1 if not
found.
• rfind(substring): Returns the highest index of the last occurrence of the substring, or -1 if not
found.
• index(substring): Similar to find(), but raises a ValueError if the substring is not found.
• rindex(substring): Similar to rfind(), but raises a ValueError if the substring is not found.
• replace(old, new): Replaces all occurrences of old with new.
• count(substring): Returns the number of non-overlapping occurrences of a substring.
• Splitting and Joining:
• split(separator): Splits the string into a list of substrings using the specified separator (defaults to
whitespace).
• rsplit(separator): Splits the string from the right.
• splitlines(): Splits the string at line boundaries.
• join(iterable): Joins elements of an iterable (e.g., a list of strings) into a single string using the
string itself as a separator.
• Checking String Properties:
• isalnum(): Checks if all characters are alphanumeric.
• isalpha(): Checks if all characters are alphabetic.
• isdigit(): Checks if all characters are digits.
• islower(): Checks if all cased characters are lowercase.
• isupper(): Checks if all cased characters are uppercase.
• isspace(): Checks if all characters are whitespace.
• startswith(prefix): Checks if the string starts with a specified prefix.
• endswith(suffix): Checks if the string ends with a specified suffix.
Example Usage:
Python
text = " Hello, Python String Methods! "
# Case conversion
print([Link]()) # Output: HELLO, PYTHON STRING METHODS!
print([Link]()) # Output: hello, python string methods!
print([Link]()) # Output: hello, python string methods!
print([Link]()) # Output: Hello, Python String Methods!
# Whitespace removal
clean_text = [Link]()
print(clean_text) # Output: Hello, Python String Methods!
# Splitting and joining
words = clean_text.split()
print(words) # Output: ['Hello,', 'Python', 'String', 'Methods!']
joined_text = "-".join(words)
print(joined_text) # Output: Hello,-Python-String-Methods!
# Replacing
replaced_text = clean_text.replace("String", "Text")
print(replaced_text) # Output: Hello, Python Text Methods!
FILES
Python offers robust capabilities for working with files, enabling programs to
interact with data stored persistently on a computer's file system.
This process is generally referred to as file handling.
Key Concepts in Python File Handling:
• Opening Files:
• The open() function is the primary method for initiating interaction with a file.
• It requires the filename as an argument and optionally accepts a mode to specify the intended
operation (reading, writing, appending, etc.).
• Example: file_object = open("my_document.txt", "r")
• File Modes:
• "r" (Read): Opens a file for reading. Raises an IOError if the file does not exist. This is the
default mode.
• "w" (Write): Opens a file for writing. Creates the file if it does not exist, or truncates (empties)
it if it already exists.
• "a" (Append): Opens a file for appending. Creates the file if it does not exist, or adds new data
to the end of an existing file.
• "x" (Create): Creates a new file. Raises an FileExistsError if the file already exists.
• "+" (Read and Write): Can be combined with other modes (e.g., "r+", "w+", "a+") to allow
both reading and writing operations.
• "b" (Binary): Can be combined with other modes (e.g., "rb", "wb", "ab") to handle files in
binary mode, suitable for non-text data like images or executables.
• Reading from Files:
• read(): Reads the entire content of the file as a single string.
• readline(): Reads a single line from the file.
• readlines(): Reads all lines from the file and returns them as a list of strings.
• Iteration: Files can be iterated over directly to process line by line efficiently.
• Writing to Files:
• write(string): Writes a string to the file.
• writelines(list_of_strings): Writes a list of strings to the file.
• Closing Files:
• It is crucial to close files after use to release system resources and ensure data integrity.
• The close() method is used for this: file_object.close().
• with open(...) as file_object: (Context Manager): This is the recommended and safest way to
handle files, as it automatically closes the file even if errors occur.
Example of File Handling:
Python
# Writing to a file
with open("[Link]", "w") as file:
[Link]("Hello, Python!\n")
[Link]("This is a new line.")
# Reading from a file
with open("[Link]", "r") as file:
content = [Link]()
print(content)
# Appending to a file
with open("[Link]", "a") as file:
[Link]("\nAppending more data.")
# Reading line by line
with open("[Link]", "r") as file:
for line in file:
print([Link]()) # .strip() removes leading/trailing wh
Reading from a file in Python involves a few key steps:
• Open the file: Use the open() function to establish a connection to the file. This function takes
the file path and the mode as arguments. For reading, the mode should be 'r'.
Python
file_object = open("your_file_name.txt", "r")
It's generally recommended to use a with statement for opening files, as it ensures the file is
automatically closed even if errors occur.
Python
with open("your_file_name.txt", "r") as file_object:
# File operations here
• Read the contents: Once the file is open, you can read its content using various methods:
o read(): Reads the entire content of the file and returns it as a single string.
Python
content = file_object.read()
print(content)
• readline(): Reads a single line from the file at a time. Each subsequent call to readline() reads the
next line.
Python
first_line = file_object.readline()
second_line = file_object.readline()
print(first_line)
print(second_line)
• readlines(): Reads all lines from the file and returns them as a list of strings, where each string
represents a line.
Python
all_lines = file_object.readlines()
for line in all_lines:
print([Link]()) # .strip() removes leading/trailing whitespace, including newline
characters
• Iterating directly over the file object: This is often the most memory-efficient way to read a
file line by line, especially for large files.
Python
for line in file_object:
print([Link]())
• Close the file (if not using with): If you didn't use a with statement, explicitly close the file using
the close() method to release system resources.
Python
file_object.close()
Writing to a file in Python involves a few key steps: opening the file.
Use the open() function to open the file. This function takes two main arguments: the file path
(or filename if in the same directory) and the mode.
• 'w' (write mode): This mode opens the file for writing. If the file already exists, its contents will
be overwritten. If the file does not exist, a new one will be created.
• 'a' (append mode): This mode opens the file for appending. If the file exists, new content will be
added to the end of the file. If the file does not exist, a new one will be created.
• 'w+' (write and read mode): This mode allows both writing and reading. It also overwrites
existing content if the file exists.
• 'a+' (append and read mode): This mode allows both appending and reading. It adds new content
to the end of the file if it exists.
Writing Data.
Once the file is opened, you can use the write() method of the file object to write
strings to the file. closing the file.
After writing, it is crucial to close the file using the close() method to ensure
all data is written and system resources are released.
A more robust and recommended approach is to use the with statement,
which automatically handles file closure, even if errors occur.
Example using with statement (recommended):
Python
# Write mode ('w') - overwrites existing content or creates a new file
with open("my_file.txt", "w") as file:
[Link]("This is the first line.\n")
[Link]("This is the second line.\n")
# Append mode ('a') - adds to the end of an existing file or creates a new file
with open("my_file.txt", "a") as file:
[Link]("This line is appended.\n")
# Writing multiple lines from a list
lines_to_write = ["Line A\n", "Line B\n", "Line C\n"]
with open("another_file.txt", "w") as file:
[Link](lines_to_write)
Example without with statement (requires manual close()):
Python
file = open("manual_close_file.txt", "w")
try:
[Link]("This file is closed manually.\n")
finally:
[Link]()
Python libraries are collections of pre-written code, including functions, classes,
and modules, that provide ready-to-use solutions for various tasks.
They significantly enhance Python's capabilities and streamline development
across diverse domains.
Key Python Libraries and their Applications:
1. Data Science and Machine Learning:
•
NumPy:
Fundamental for numerical computing, especially with multi-dimensional arrays and matrices.
•
Pandas:
Essential for data manipulation and analysis, offering powerful data structures like DataFrames.
•
Matplotlib:
A widely used library for creating static, interactive, and animated visualizations in Python.
•
Seaborn:
Built on Matplotlib, providing a high-level interface for drawing attractive and informative
statistical graphics.
•
SciPy:
Offers modules for scientific and technical computing, including optimization, linear algebra,
integration, and statistics.
•
Scikit-learn:
A comprehensive library for machine learning, providing various algorithms for classification,
regression, clustering, and more.
• TensorFlow & Keras:
Popular libraries for deep learning, enabling the creation and training of neural networks.
• PyTorch:
Another prominent open-source machine learning library, known for its flexibility and dynamic
computational graph.
2. Web Development:
• Django: A high-level web framework that encourages rapid development and clean, pragmatic
design.
• Flask: A lightweight and flexible micro-framework for building web applications.
• FastAPI: A modern, fast (high-performance) web framework for building APIs with Python
3.7+ based on standard Python type hints.
3. Web Scraping and Automation:
• Requests: Simplifies making HTTP requests to interact with web services.
• Beautiful Soup: A library for parsing HTML and XML documents, useful for web scraping.
• Scrapy: A powerful framework for web crawling and scraping.
• Selenium: Used for automating web browser interactions, often employed in testing and data
extraction.
4. Other Notable Libraries:
• Pillow: For image processing and manipulation.
• Pygame: For game development.
• NLTK & spaCy: For natural language processing (NLP).
• SQLAlchemy: A powerful Object Relational Mapper (ORM) for interacting with databases.
These are just a few examples, and the Python ecosystem boasts a vast array of
libraries catering to virtually every programming need.
They allow developers to leverage existing solutions, accelerate development,
and build sophisticated applications with ease.
Python libraries are collections of modules containing pre-written code,
functions, and classes that provide specific functionalities, making it easier to develop
applications and avoid writing code from scratch.
Importing these libraries allows you to access and utilize their contents within
your Python programs.
There are several ways to import libraries in Python: Import the entire library.
This imports the entire library, and you access its components by prefixing them with the library
name.
Python
import math
result = [Link](25)
print(result)
Import a specific function or class.
This allows you to import only specific components from a library, making them directly
accessible without the library name prefix.
Python
from math import sqrt
result = sqrt(25)
print(result)
Import a library with an alias.
This imports the entire library but assigns it a shorter, more convenient alias for easier use. This
is commonly used for libraries like NumPy and Pandas.
Python
import pandas as pd
data = [Link]({'col1': [1, 2], 'col2': [3, 4]})
print(data)
Important considerations for importing libraries:
• Installation:
Before importing, ensure the library is installed in your Python environment. You can typically
install libraries using pip, the Python package installer (e.g., pip install library_name).
• Module vs. Package:
A module is a single Python file (.py), while a package is a directory containing multiple
modules and an __init__.py file. The import statement works for both.
• from ... import * (Import all names):
While possible, importing all names from a module using from module import * is generally
discouraged as it can lead to name clashes and make it harder to track where specific functions
originated.
• Standard Library:
Python comes with a rich standard library of built-in modules that are readily available for
import without needing separate installation.