V - Functions and Modularization
- Defining Functions
- Returning Values
- Function Arguments
- Lambda Functions
- Recursive Functions
- Nested Functions
- Variable Scope
- Importing Functions and Modules
- Choosing the Right Execution Mode
- Handling Command-Line Arguments with argparse
- Code Style and Readability
- Naming Conventions
- Commenting and Documentation
- Efficient Code Writing
Python is a high-level, interpreted programming language that is known for its simplicity and readability. It is widely used for a variety of tasks, including web development, data science, artificial intelligence, automation, and scripting. Python is popular among both beginners and experienced developers due to its clear syntax and large ecosystem of libraries and frameworks.
Key Characteristics:
- High-level: Python allows developers to write code that is closer to human language than machine language, which makes it easier to understand and use. The language handles many of the complexities of low-level operations, like memory allocation, so developers can focus more on solving problems rather than managing hardware resources.
- Interpreted: Python code is executed line-by-line by an interpreter, which makes it easy to test and debug.
- Extensive Libraries: Python boasts a huge selection of built-in and third-party libraries for tasks like web scraping, data visualization, and machine learning.
- Community Support: Python has an active and helpful community, making it easy to find tutorials, documentation, and solutions to problems.
Python can be easily installed on various operating systems. The Conda setup covered in the previous tutorial already includes Python as part of the installation. If you want to install Python manually, you can download it from the official website and follow the installation instructions based on your operating system.
If you're using Conda, Python will be pre-installed, and you can confirm this by running the following command in the terminal:
$ python --versionThis will display the installed version of Python. You can also use python3 in some environments, especially if multiple versions of Python are installed.
Python code can be executed in several ways:
-
Interactive Mode:
You can run Python interactively directly from the terminal by simply typing
python(orpython3). This will launch the Python shell where you can execute code line by line.$ python >>> print("Hello, World!") Hello, World! >>> quit() # Exits the interactive mode
In this mode, you can quickly test small snippets of code.
-
Scripts:
Python scripts are saved with the
.pyextension and can be run from the command line.$ python script.py
You can add a "shebang" (
#!/usr/bin/env python3) at the top of your Python file. This enables the script to be executed directly from the command line without needing to explicitly invoke the Python interpreter.$ ./script.py
⚠️ You may need to ensure the script has the correct permissions:$ chmod +x script.py
-
Notebooks:
For a more interactive and flexible environment, Jupyter Notebooks allow you to run Python code in interactive cells, which can also contain code, text (written in Markdown), and rich media outputs (such as interactive plots or images).
When executing Python code in a notebook, the cell will process the code and display the result directly below the input. Jupyter uses JavaScript to manage interactions between the notebook interface and Python, creating a hybrid environment ideal for experimentation, data analysis, and documentation.
Variables are used to store values that you can refer to later in your program. You can assign a value to a variable by using the = operator.
A variable that has been assigned a value is considered declared.
age = 25The variable age is now assigned the value 25.
name = "Alice"The variable name is now assigned the value Alice.
") are necessary, otherwise python would think Alice is the name of another, previously-declared, variable from which we want to assign the value to age.
Numbers (such as 25) cannot be used as variables, so they do not need to be surounded by quotes ".
You can assign a new value to a variable at any time:
age = 30The variable age is now assigned the value 30.
Variable manipulation is at the core of programming, forming the foundation for more complex logic, functionality, and flexibility.
Comments are used to annotate your code with explanations or notes. They are ignored by the Python interpreter and are essential for making your code more understandable.
- Single-line comments: You can add a comment by starting the line with a
#.
# This is a comment
x = 10 # This is an inline comment- Multi-line comments: Although Python doesn't have a specific syntax for multi-line comments, you can use triple quotes (
""" """or''' ''') to create block comments. These are often used for docstrings (documentation strings), but can also be used as comments.
"""
This is a multi-line comment.
It can span several lines.
"""
x = 20Functions are a key part of programming that allow you to run specific tasks by calling pre-defined blocks of code. By using functions, you can simplify your code and perform advanced operations. Here are some basic functions:
-
The
print()function is used to output information to the console. It is one of the most commonly used functions for displaying results or debugging information.print("Hello, world!") # Output: Hello, world!
-
The
input()function is used to capture input from the user.name = input("Enter your name: ") print("Hello,", name)
Functions in Python are called by using their name followed by parentheses (). Inside the parentheses, you can pass one or more parameters, separated by commas. These parameters are the inputs that the function uses to perform its task. Just like variables, functions are recognizable by their name, and the parentheses indicate that you're calling, or invoking, the function. For example, in print("Hello, world!"), print is the function, and "Hello, world!" is the parameter being passed to it.
Some functions will return a value after performing their task. This returned value can then be assigned to a variable for further use. The input() function, for instance, captures the user's input and returns it as a string, which can be stored in a variable.
In programming, variables have a data type that defines the kind of information they can store. Data types determine what operations can be applied to a variable and which functions can accept it. Conversely, most functions expect their parameters to have specific data types to work correctly. In Python, the data type of a variable is assigned implicitly and dynamically, meaning you don’t need to declare it explicitly: it’s automatically assigned based on the value the variable holds.
-
Here are some of Python's built-in data types:
int: Integer numbers, e.g., 5, -3, 42float: Floating-point numbers, e.g., 3.14, -2.5, 0.99bool: Boolean values, eitherTrueorFalsestr: Strings, or sequences of characters, e.g., "hello", "Alice", "42". Strings are always recognizable by the surrounding quotes ("or').None: A special type used to represent the absence of a value or a null value. It is often used to indicate that a variable has no value assigned or that a function does not return anything.
-
You can check the type of a variable using the
type()function:x = 10 print(type(x)) # Output: <class 'int'> y = 3.14 print(type(y)) # Output: <class 'float'> z = "Hello" print(type(z)) # Output: <class 'str'> is_active = True print(type(is_active)) # Output: <class 'bool'> result = None print(type(result)) # Output: <class 'NoneType'>
-
You can also convert between types using functions like
int(),float(), andstr():x = "10" x = int(x) # Convert string to integer y = 3 y = str(y) # Convert integer to string z = "3.14" z = float(z) # Convert string to float
⚠️ However, the conversion (also named casting) needs to make sense and can sometimes be confusing, especially when working with booleans. For instance, when you cast a non-zero number to a boolean, it will be interpreted asTrue, and when you cast0or an empty string"", it will be interpreted asFalse:a = 5 b = 0 c = "" d = "Hello" print(bool(a)) # Output: True (since 5 is non-zero) print(bool(b)) # Output: False (since 0 is zero) print(bool(c)) # Output: False (since an empty string is considered False) print(bool(d)) # Output: True (non-empty string is considered True)
This can be tricky at times, so it's important to ensure that the type conversions you make align with your intended behavior in the program.
-
Arithmetic operators:
Python supports a wide variety of arithmetic operators for numerical calculations:
- Addition (
+): Adds two numbers. - Subtraction (
-): Subtracts the second number from the first. - Multiplication (
*): Multiplies two numbers. - Division (
/): Divides the first number by the second, resulting in a float. - Exponentiation (
**): Raises the first number to the power of the second. - Modulus (
%): Returns the remainder of a division. - Floor Division (
//): Divides the first number by the second and returns the largest integer less than or equal to the result.
Here are some examples of using these operations:
x = 10 y = 3 print(x + y) # Output: 13 print(x - y) # Output: 7 print(x * y) # Output: 30 print(x / y) # Output: 3.333... print(x ** y) # Output: 1000 print(x % y) # Output: 1 print(x // y) # Output: 3
- Addition (
-
Compound assignment operators
Python also offers compound assignment operators, which allow you to perform arithmetic operations and assignments in one step. For example:
- Addition Assignment (
+=): Adds the right operand to the left operand and assigns the result to the left operand. - Subtraction Assignment (
-=): Subtracts the right operand from the left operand and assigns the result to the left operand. - Multiplication Assignment (
*=): Multiplies the left operand by the right operand and assigns the result to the left operand. - Division Assignment (
/=): Divides the left operand by the right operand and assigns the result to the left operand.
Some examples:
x = 10 y = 3 x += y # x = x + y, now x is 13 print(x) # Output: 13 x *= 2 # x = x * 2, now x is 26 print(x) # Output: 26
Compound assignment operators can make your code more concise and help you avoid repeating the variable name when performing operations.
- Addition Assignment (
-
Comparison operators:
Comparison operators in Python are used to compare two values or variables. These operators return
TrueorFalsebased on the comparison results, and they are often used in conditional statements and loops.Here are the main comparison operators:
- Equal to (
==): ReturnsTrueif the two operands are equal. - Not equal to (
!=): ReturnsTrueif the two operands are not equal. - Greater than (
>): ReturnsTrueif the left operand is greater than the right operand. - Less than (
<): ReturnsTrueif the left operand is less than the right operand. - Greater than or equal to (
>=): ReturnsTrueif the left operand is greater than or equal to the right operand. - Less than or equal to (
<=): ReturnsTrueif the left operand is less than or equal to the right operand.
Examples:
x = 10 y = 5 print(x == y) # Output: False (x is not equal to y) print(x != y) # Output: True (x is not equal to y) print(x > y) # Output: True (x is greater than y) print(x < y) # Output: False (x is not less than y) print(x >= y) # Output: True (x is greater than or equal to y) print(x <= y) # Output: False (x is not less than or equal to y)
Comparison operators are essential in decision-making processes, helping you control the flow of your program based on conditions. They are commonly used in
ifstatements, loops, and while checking the truth of expressions. - Equal to (
-
Logical operators:
Python provides logical operators for combining boolean statements:
- And (
and): ReturnsTrueif both conditions are true. - Or (
or): ReturnsTrueif at least one of the conditions is true. - Not (
not): Reverses the truth value of the condition.
Examples:
x = 10 y = 5 print(x > 5 and y < 10) # Output: True (both conditions are true) print(x > 5 or y > 10) # Output: True (at least one condition is true) print(not(x > 5)) # Output: False (x > 5 is true, but "not" makes it false)
- And (
Strings in Python are sequences of characters. You can manipulate them in various ways.
-
Indexing: You can access individual characters in a string by using square brackets (
[]). Python uses zero-based indexing, meaning the first character is at index 0. You can also use negative indexing, which starts from the end of the string (with-1being the last character).s = "Python" print(s[0]) # Output: P print(s[1]) # Output: y print(s[-1]) # Output: n (last character) print(s[-2]) # Output: o (second to last character)
-
Slicing: You can extract a portion of a string using the slicing syntax
s[start:end], wherestartis the index of the first character, andendis the index of the character just past the last character you want.s = "Python" print(s[1:4]) # Output: yth (from index 1 to 3) print(s[-3:-1]) # Output: ho (from third to last character to the second to last character)
-
String Methods: Python provides a number of built-in methods to manipulate strings. Some common methods include:
.lower(): Converts all characters to lowercase..upper(): Converts all characters to uppercase..strip(): Removes whitespace from both ends of the string..replace(old, new): Replaces occurrences of a substring with a new string.
s = " Hello, World! " print(s.lower()) # Output: hello, world! print(s.upper()) # Output: HELLO, WORLD! print(s.strip()) # Output: Hello, World! print(s.replace("Hello", "Hi")) # Output: Hi, World!
-
String Formatting: Python allows you to format strings in a readable way using f-strings, the
.format()method, or the%operator.name = "Alice" age = 30 # Using f-strings print(f"My name is {name} and I am {age} years old.") # Using .format() method print("My name is {} and I am {} years old.".format(name, age)) # Using the `%` operator print("My name is %s and I am %d years old." % (name, age)) # Outputs: My name is Alice and I am 30 years old.
-
Concatenation and Repetition: You can concatenate (combine) strings with the
+operator and repeat them with the*operator.greeting = "Hello" name = "Alice" # Concatenate print(greeting + " " + name) # Output: Hello Alice # Repeat print("Hi! " * 3) # Output: Hi! Hi! Hi!
-
Checking Substrings: You can check if a substring exists in a string using the
inandnot inoperators.sentence = "Hello, world!" # Check if 'world' is in the sentence print("world" in sentence) # Output: True # Check if 'goodbye' is not in the sentence print("goodbye" not in sentence) # Output: True
-
Special Characters and Escape Sequences: Strings can contain special characters, which are often represented by escape sequences. An escape sequence starts with a backslash (
\) and allows you to include characters that are difficult or impossible to type directly, like newline (\n), tab (\t), or a backslash itself (\\).# Newline print("Hello\nWorld!") # Output: Hello (new line) World! # Tab print("Hello\tWorld!") # Output: Hello World! # Backslash print("C:\\Program Files\\Python") # Output: C:\Program Files\Python
Additionally, you can use escape sequences to include quotes within strings without ending the string (you can also use different types of quotes for the string and the quotes inside it).
print("She said, \"Hello, World!\"") # Output: She said, "Hello, World!" print('She said, "Hello, World!"') # Output: She said, "Hello, World!" print('It\'s a sunny day!') # Output: It's a sunny day! print("It's a sunny day!") # Output: It's a sunny day!
In Python, there are two common ways to use functions: method calls and function calls. Both involve calling functions, but they have different syntaxes and purposes.
-
Method call (
var.function()): This is when you call a function that is associated with a particular variable or object. The function is tied to the object and is called using dot notation. The variable (var) is the object that the method operates on. For example, strings have built-in methods like.lower()or.upper(), which can be used to manipulate the string directly. -
Function call (
function(var)): This is when you call a standalone function and pass variables or values to it as parameters. The function is independent of any particular variable or object, and it operates on the arguments you provide.text = "Hello" print(text.lower()) # Output: hello
In this case,
lower()is a method of thetextstring object, and it operates specifically on that object. On the other hand,print()is a standalone function and isn't tied to a specific object.
In Python, data structures are special data types that allow us to store, organize, and manipulate collections of values efficiently. They help in structuring our programs and optimizing operations like searching, sorting, and accessing elements. Python provides several built-in data structures, each suited for different use cases.
A list is a collection of items that can store multiple values in an ordered sequence. Lists are mutable, meaning their contents can be changed after creation.
-
Creating a List
Lists are defined using square brackets
[], with elements separated by commas.# Creating a list of numbers numbers = [1, 2, 3, 4, 5] # Creating a mixed-type list - ⚠️Not advised mixed = [1, "hello", 3.5, True]
-
Accessing Elements
Elements in a list can be accessed using zero-based indexing:
numbers = [10, 20, 30, 40] print(numbers[0]) # First element: 10 print(numbers[2]) # Third element: 30
-
Slicing Lists
Slicing allows extracting a subset of a list using the
[start:stop:step]notation:numbers = [0, 1, 2, 3, 4, 5, 6] print(numbers[1:4]) # [1, 2, 3] (from index 1 to 3) print(numbers[:3]) # [0, 1, 2] (first three elements) print(numbers[3:]) # [3, 4, 5, 6] (from index 3 to the end) print(numbers[::2]) # [0, 2, 4, 6] (every second element) print(numbers[::-1]) # [6, 5, 4, 3, 2, 1, 0] (reverse the list)
-
Modifying a List
Lists support modification of elements:
numbers[1] = 25 # Changing the second element print(numbers) # [10, 25, 30, 40]
-
Adding and Removing Elements
-
Appending elements to the end of a list:
numbers.append(50) # [10, 25, 30, 40, 50]
-
Inserting elements at a specific index:
numbers.insert(2, 15) # Insert 15 at index 2
-
Removing elements:
numbers.remove(30) # Removes the first occurrence of 30 last_item = numbers.pop() # Removes and returns the last element
-
A tuple is an immutable sequence of elements, meaning it cannot be modified after creation. Tuples are useful when you want to store a fixed collection of items.
-
Creating a Tuple
Tuples use parentheses
()or can be created without brackets:coordinates = (10.5, 20.3) single_element = (42,) # Note the comma is necessary for single-element tuples
-
Accessing Tuple Elements
Like lists, elements in a tuple can be accessed via indexing and slicing:
tuple_data = (10, 20, 30, 40, 50) print(tuple_data[0]) # Output: 10 print(tuple_data[1:4]) # Output: (20, 30, 40) print(tuple_data[::-1]) # Output: (50, 40, 30, 20, 10)
Python data types can be categorized based on whether they allow modifications after creation:
- Mutable types: Can be modified (e.g., lists, dictionaries, sets)
- Immutable types: Cannot be modified (e.g., tuples, strings, numbers)
Example:
name = "Alice"
# name[0] = "B" # This will raise an error because strings are immutable
numbers = [1, 2, 3]
numbers[0] = 10 # Allowed because lists are mutableA dictionary is an unordered collection of key-value pairs, where each key is unique (values can have duplicates). Dictionaries allow fast lookups and modifications.
-
Creating a Dictionary
Dictionaries are created using curly braces
{}:person = { "name": "Alice", "age": 25, "city": "New York" }
-
Accessing Values
Values are retrieved using keys:
print(person["name"]) # Output: Alice
-
Adding and Modifying Key-Value Pairs
person["age"] = 26 # Modify existing key person["job"] = "Engineer" # Add a new key-value pair
-
Removing Elements
del person["city"] # Removes the key-value pair with key "city" age = person.pop("age") # Removes and returns the value for "age"
A set is an unordered collection of unique elements. Sets are useful for eliminating duplicates and performing set operations.
-
Creating a Set
fruits = {"apple", "banana", "cherry"}
-
Adding and Removing Elements
fruits.add("orange") # Add an element fruits.remove("banana") # Remove an element
-
Set Operations
a = {1, 2, 3, 4} b = {3, 4, 5, 6} print(a | b) # Union: {1, 2, 3, 4, 5, 6} print(a & b) # Intersection: {3, 4} print(a - b) # Difference: {1, 2}
Certain operations apply to most common built-in data structures in Python. Here's an overview:
-
Length (
len()): Returns the number of elements in the structure.- Works for lists, strings, tuples, sets, and dictionaries.
numbers = [1, 2, 3, 4] print(len(numbers)) # Output: 4
-
Membership (
in): Checks if an element exists within the structure and returns a boolean.- Works for lists, strings, tuples, sets, and dictionaries (checks keys).
numbers = [1, 2, 3, 4] print(2 in numbers) # Output: True print(5 in numbers) # Output: False
-
Equality (
==): Checks if two structures have the same elements in the same order. Use!=for inequality.- Works for lists, strings, tuples, sets, and dictionaries.
numbers = [1, 2, 3, 4] print(numbers == [1, 2, 3, 4]) # Output: True print(numbers == [1, 2, 3]) # Output: False print(numbers != [1, 2, 3, 5]) # Output: True
-
String Joining (
str.join()): This method takes an iterable (like a list) and joins its elements into a single string, using the string it is called on as a separator (delimiter) between elements.- Works for lists and other iterable sequences containing strings.
words = ['Python', 'is', 'great'] sentence = ' '.join(words) print(sentence) # Output: Python is great hyphenated = '-'.join(words) print(hyphenated) # Output: Python-is-great
Another operation that applies to all data structures is the iteration (using the for statement), which we’ll cover in the next section on Control Flow.
Control flow determines the order in which statements are executed in a program. Python provides structures like conditional statements and loops to control execution based on conditions and repetitions.
Conditional statements are used to execute specific blocks of code based on certain conditions. Python uses if, elif, and else to define these conditions.
-
ifStatement: Executes a block of code if a condition isTrue.age = 18 if age >= 18: print("You are an adult.")
-
if-elseStatement: Provides an alternative action if the condition isFalse.age = 16 if age >= 18: print("You are an adult.") else: print("You are a minor.")
-
if-elif-elseStatement: Checks multiple conditions in sequence.score = 85 if score >= 90: print("Grade: A") elif score >= 80: print("Grade: B") elif score >= 70: print("Grade: C") else: print("Grade: F")
if, elif, and else must be indented consistently.
-
Nest conditional statements: You can also nest conditional statements by adding further indented blocks inside existing blocks. This allows you to create more complex decision trees.
age = 20 if age >= 18: if age >= 21: print("You are allowed to drink alcohol.") else: print("You are an adult, but not allowed to drink alcohol.") else: print("You are a minor.")
-
match-caseStatement: Introduced in Python 3.10, this allows for pattern matching. It's similar to switch statements found in other languages and is useful for matching complex data structures or multiple possible conditions.day = "Monday" match day: case "Monday": print("Start of the week!") case "Friday": print("Almost weekend!") case _: print("Mid-week day.")
⚠️ Tip: If you're using an older version of Python, you can use traditionalif-elif-elsestatements instead ofmatch-case, as the latter was introduced in Python 3.10 and is not available in earlier versions.
Loops allow us to execute a same block of code multiple times.
-
forloopsA
forloop iterates over a sequence (like a list, string, or range) and executes a block of code for each element.fruits = ["apple", "banana", "cherry"] for fruit in fruits: print(fruit)
Looping with
range():for i in range(5): print(i) # Outputs 0, 1, 2, 3, 4
-
whileloopsA
whileloop runs as long as a condition remainsTrue.count = 0 while count < 3: print("Count:", count) count += 1
⚠️ Beware of infinite loops: Ensurewhileloops have an exit condition to prevent infinite execution.
Loop control statements modify the flow inside loops:
-
break: Exits the loop immediately.for num in range(10): if num == 5: break print(num) # Stops at 4
-
continue: Skips the current iteration and proceeds to the next.for num in range(5): if num == 2: continue print(num) # Skips 2
-
pass: A placeholder when no action is required.for num in range(3): if num == 1: pass # Does nothing else: print(num)
Comprehensions provide a concise and readable way to create new data structures through iteration. Python supports comprehensions for various data types:
-
List Comprehension:
Create lists from an iterable in a single line. You can also add conditions to filter elements.squares = [x ** 2 for x in range(5)] # Output: [0, 1, 4, 9, 16] even_numbers = [x for x in range(10) if x % 2 == 0] # Output: [0, 2, 4, 6, 8]
-
Dictionary Comprehension:
Create dictionaries with key-value pairs from an iterable.square_dict = {x: x ** 2 for x in range(5)} # Output: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
-
Set Comprehension:
Create sets from an iterable, ensuring uniqueness.unique_squares = {x ** 2 for x in range(5)} # Output: {0, 1, 4, 9, 16}
-
Generator Comprehension (More advanced): Similar to list comprehensions but returns a generator object for memory efficiency.
squares_gen = (x ** 2 for x in range(5))
Functions are a fundamental part of Python programming, allowing you to write reusable blocks of code that can be called multiple times. In the previous sections, you encountered and used built-in functions (such as print(), input(), and len()). Now, we will explore how you can define our own functions and structure your code more effectively.
In Python, we define functions using the def keyword, followed by the function name and parentheses (). The function body must be indented.
Here's a basic function definition and usage:
# Defining a function
def greet():
print("Hello, world!")
# Calling the function
greet() # Output: Hello, world!A function can return a value using the return statement. This allows functions to pass data back to the caller.
def add(a, b):
return a + b
result = add(3, 5)
print(result) # Output: 8A function without a return statement returns None by default.
Functions can take parameters to accept input values. Python supports different types of arguments.
def greet(name, message):
print(f"{message}, {name}!")Positional vs Keyword Arguments
- Positional Arguments: Values are assigned based on the order in which they are passed.
- Keyword Arguments: Values are assigned using parameter names, making the order flexible.
# Positional Arguments
greet("Alice", "Hello") # Output: Hello, Alice!
# Keyword Arguments
greet(message="Hi", name="Bob") # Output: Hi, BobDefault Values
You can assign default values to parameters. If an argument is not provided, the default value is used.
def greet(name, message="Hello"):
print(f"{message}, {name}!")
greet("Alice") # Output: Hello, Alice!
greet("Bob", "Hi") # Output: Hi, Bob!A lambda function is a small anonymous function defined using the lambda keyword. It can have multiple parameters but only one expression.
# Lambda function to add two numbers
add = lambda x, y: x + y
print(add(3, 5)) # Output: 8Lambda functions are useful when you need a short function for immediate use, such as with map(), filter(), and sorted().
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared) # Output: [1, 4, 9, 16, 25]A recursive function is a function that calls itself in order to solve a problem. These functions are useful for problems that can be broken down into smaller instances of the same problem, such as computing factorials or Fibonacci sequences.
def factorial(n):
if n == 0:
return 1
return n * factorial(n - 1)
print(factorial(5)) # Output: 120In Python, you can define functions inside other functions. These are called nested functions. Nested functions are useful for encapsulating logic that is only relevant within the scope of the outer function. They help in keeping code modular and clean by limiting the scope of helper functions.
def outer_function():
def inner_function():
print("This is an inner function")
inner_function()
outer_function() # Output: This is an inner functionIn Python, variables have different scopes (or visibilities) that determine where they can be accessed. There are two primary types of variable scope: local and global.
- Local variables are defined inside a function and can only be accessed within that function.
- Global variables are defined outside any function and can be accessed anywhere in the script.
Example:
global_var = "I am global"
def example():
local_var = "I am local"
print(local_var) # Accessible inside function
print(global_var) # Accessible inside function
example()
print(local_var) # Error: local_var is not accessible here!If you want to modify a global variable inside a function, you must use the global keyword:
global_count = 0
def increment():
global global_count
global_count += 1
increment()
print(global_count) # Output: 1Python promotes code reusability through modules and packages—collections of functions, classes, and variables. You can import modules or specific functions from them to organize and reuse code effectively.
-
Importing an Entire Module
You can import an entire module and access its functions using
module.function().import math print(math.sqrt(16)) # Output: 4.0
-
Importing Specific Functions
You can also import specific functions from a module to use them directly.
from math import sqrt print(sqrt(25)) # Output: 5.0
-
Renaming Modules or Functions
To avoid name conflicts or shorten long names, you can rename a module or function during import using the
askeyword.import math as m print(m.pi) # Output: 3.141592653589793
-
Creating Your Own Modules
You can create your own Python module by writing functions in a
.pyfile and importing it into other scripts.Example: Create a file
my_module.py:# my_module.py def greet(name): return f"Hello, {name}!"
Then, in another script, import and use the module:
import my_module print(my_module.greet("Alice")) # Output: Hello, Alice!
-
Using Packages
A package is a collection of modules, typically organized in directories. You can import specific modules from a package. For example, Python’s built-in
datetimepackage provides various modules for working with dates and times. Here’s how you can use it:import datetime current_time = datetime.datetime.now() print(current_time) # Output: Current date and time
If you want to import specific submodules from a package, you can do so like this:
from datetime import datetime current_time = datetime.now() print(current_time) # Output: Current date and time
This allows you to efficiently work with different components of a package, depending on your needs.
Using modules, packages, and functions in your code enhances organization, readability, and reusability, making your projects easier to maintain and scale.
File handling is an essential part of programming that allows us to read from and write to external files. Python provides built-in functions to work with files efficiently.
In Python, we use the open() function to work with files. The open() function can return a file object, which allows us to read from or write to the file. When opening a file, we must specify a file mode:
r: Read mode (default). Opens the file for reading. If the file does not exist, it raises an error.w: Write mode. Creates a new file if it does not exist or overwrites an existing file.a: Append mode. Opens the file for writing but does not overwrite existing content; instead, it adds to the end of the file.rb,wb,ab: Same asr,w, anda, but for binary files.
The with statement ensures proper resource management by automatically closing the file after reading or writing, which is important for preventing file corruption or memory leaks.
-
Reading Files
# Read entire file with open("example.txt", "r") as file: content = file.read() print(content) # Read file line by line with open("example.txt", "r") as file: lines = file.readlines() for line in lines: print(line.strip()) # Removes extra newlines
-
Writing to Files
# Write content to file (overwrites) with open("example.txt", "w") as file: file.write("Hello, Python!\n") # Append content to file with open("example.txt", "a") as file: file.write("This is an appended line.\n")
Writing clean, efficient, and readable code is essential for becoming a proficient Python developer. Following best practices ensures maintainability, collaboration, and scalability. This section covers key principles to improve your coding skills.
Python can be run in different modes, each suitable for specific tasks:
- Script Mode: Best for standalone applications, automation, or production-level code. You execute a Python file directly as an independent program.
- Interactive Mode: Ideal for quick testing, debugging, or trying out small code snippets in the Python shell (REPL).
- Jupyter Notebooks: Perfect for data analysis, visualization, and documentation, offering an interactive environment with inline outputs and plots.
Best Practice:
Use if __name__ == "__main__" to structure your code so that certain parts only run when the script is executed directly (not when it is imported as a module). This ensures flexibility and modularity.
The argparse module is designed to simplify the process of handling command-line arguments. It allows you to build user-friendly command-line interfaces by defining required and optional arguments, performing type validation, and generating automatic help messages and error handling.
- Basic Example:
import argparse
# Set up the argument parser
parser = argparse.ArgumentParser(description="Greet the user by name.")
parser.add_argument("name", type=str, help="Your name")
# Parse the command-line arguments
args = parser.parse_args()
# Output the greeting message
print(f"Hello, {args.name}!")How it works:
ArgumentParser: Initializes the parser that will handle the arguments.add_argument: Adds a specific argument, in this case,name, which is required and expects a string value.parse_args: Parses the command-line input and stores the result inargs, making it accessible in your script.
To run the script from the command line, simply pass the argument like so:
python script.py AliceOutput:
Hello, Alice!
This structure enables your scripts to interact with the user via command-line input, making them more flexible and scalable for various use cases.
Following a consistent style improves code readability and maintainability.
-
Follow PEP 8 (Python Enhancement Proposal 8)
- Use 4 spaces per indentation level.
- Limit line length to 79 characters.
- Add blank lines to separate logical sections.
- Avoid unnecessary whitespace inside parentheses, brackets, and braces.
- Use
isandis notinstead of==and!=for comparing withNone.
-
Use Meaningful Variable Names
- Names should be descriptive and clear.
- Example of a bad variable name:
a = 25 # What does 'a' represent?
- Example of a good variable name:
age_of_user = 25
-
Keep Functions Short and Focused
- A function should ideally perform a single task.
- If a function becomes too long, consider breaking it into smaller functions.
Consistent naming makes code more readable and maintainable.
-
Variables and Functions: Use
snake_case(lowercase with underscores).user_name = "Alice" def calculate_average(scores): return sum(scores) / len(scores)
-
Constants: Use
UPPER_CASE.MAX_CONNECTIONS = 100
-
Class Names: Use
PascalCase(also calledCamelCase).class DataProcessor: pass
Well-documented code helps others (and your future self) understand your intentions.
-
Write Clear and Concise Comments
- Explain why something is done rather than what it does.
- Avoid redundant comments:
x = x + 1 # Increments x by 1 (redundant)
-
Use Docstrings for Functions and Modules
- A docstring (
"""...""") is a string at the beginning of a function, class, or module that describes its purpose.
def add_numbers(a, b): """Returns the sum of two numbers.""" return a + b
- A docstring (
Writing efficient code helps optimize performance and maintainability.
-
Avoid Redundant Code
- Use loops, functions, and list comprehensions to avoid repetition.
# Instead of this: numbers = [1, 2, 3, 4] squares = [] for num in numbers: squares.append(num ** 2) # Use list comprehension: squares = [num ** 2 for num in numbers]
-
Write Modular Code
- Break down your code into reusable functions and modules.
def greet_user(name): return f"Hello, {name}!" print(greet_user("Alice"))
-
Avoid Global Variables
- Global variables can lead to unexpected side effects.
- Use function parameters and return values instead.
# Instead of modifying a global variable: total = 0 def add_to_total(value): global total total += value # Pass the value instead: def calculate_total(total, value): return total + value
-
Use Built-in Functions Whenever Possible
- Python provides many built-in functions that are optimized for performance.
# Instead of manually summing a list: total = 0 for num in [1, 2, 3, 4]: total += num # Use sum(): total = sum([1, 2, 3, 4])
Following these best practices should help you write cleaner, more efficient, and maintainable Python code.