Python refresher
This post is a quick refresher on python for experience engineer to start writing code.
Comments in Python
Single-line Comments:
- Start with a hash symbol (
#
). - Everything after the
#
on the same line is ignored by the Python interpreter.
# This is a single-line comment
x = 5 # This is an inline comment
Multi-line Comments (Docstrings):
- Enclosed within triple quotes (
"""
or'''
). - Often used for documenting functions, classes, and modules.
"""
This is a multi-line comment.
It can span multiple lines.
"""
def my_function():
"""This is a docstring for the my_function."""
pass
Use docstrings for functions, classes, and modules: Docstrings provide a standard way to document your code and are often used by tools like Sphinx to generate documentation.
def calculate_area_of_circle(radius):
"""
Calculates the area of a circle.
Args:
radius: The radius of the circle.
Returns:
The area of the circle.
"""
import math
return math.pi * radius * radius
# Get user input for radius
radius = float(input("Enter the radius of the circle: "))
# Calculate and print the area
area = calculate_area_of_circle(radius)
print(f"The area of the circle is: {area}")
Variables and Data Types
Python is a dynamically typed language. Following are few highlights.
No Explicit Type Declarations: You don’t need to explicitly declare the data type of a variable before assigning a value to it. Following is few example.
x = 10 # x is automatically inferred as an integer
x = "hello" # Now x is a string
my_variable = None # It represents the absence of a value.
temperature = 25.5
is_raining = True
Type Inference: Python automatically determines the data type of a variable based on the value assigned to it.
Flexibility: This dynamic typing allows for more flexibility and rapid development, as you don’t have to worry about type declarations.
Type Checking (Optional): You can use type hints to provide information about the expected data types for variables and function arguments. This is optional but can improve code readability and help catch errors early on.
def greet(name: str) -> str:
return f"Hello, {name}!"
print()
is used to displays output to the console. Following is syntax.
print(value1, value2, ..., sep=' ', end='\n')
value1, value2, ...
: The values you want to print (can be variables, strings, numbers, etc.).sep
: The separator between values (default is a space ' ').end
: The character to print at the end (default is a newline '\n').
Following is example to use print.
print("Hello, world!")
print("My name is", "Alice")
print(10 + 5)
print("The result is:", 10 * 2, sep=" - ")
print("Hello", end=" ")
print("world!")
input()
is used to gets input from the user. Following is syntax.
input(prompt="")
prompt
: An optional string that is displayed to the user as a message.
Following is example for reference.
name = input("Enter your name: ")
print("Hello,", name)
Combining print()
and input()
age = int(input("Enter your age: "))
print("You are", age, "years old.")
Operators
Arithmetic operators
Arithmetic operators are used to perform mathematical operations on numbers. Following is example to show few.
num1 = 10
num2 = 3
sum_result = num1 + num2 # 10 + 3 = 13
difference_result = num1 - num2 # 10 - 3 = 7
product_result = num1 * num2 # 10 * 3 = 30
division_result = num1 / num2 # 10 / 3 = 3.3333333333333335
floor_division_result = num1 // num2 # 10 // 3 = 3
modulus_result = num1 % num2 # 10 % 3 = 1
exponentiation_result = num1 ** 2 # 10 ** 2 = 100
print("Sum:", sum_result)
print("Difference:", difference_result)
print("Product:", product_result)
print("Division:", division_result)
print("Floor Division:", floor_division_result)
print("Modulus:", modulus_result)
print("Exponentiation:", exponentiation_result)
Comparison operators
Comparison operators are used to compare values and return a Boolean value (True or False). They are essential for making decisions in your code (e.g., within if
statements).
Here’s a list of common comparison operators:
Equal to (==
)
- Checks if two values are equal.
- Example:
5 == 5
returnsTrue
,5 == 3
returnsFalse
Not Equal to (!=
)
- Checks if two values are not equal.
- Example:
5 != 3
returnsTrue
,5 != 5
returnsFalse
Greater Than (>
)
- Checks if the left operand is greater than the right operand.
- Example:
5 > 3
returnsTrue
,3 > 5
returnsFalse
Less Than (<
)
- Checks if the left operand is less than the right operand.
- Example:
3 < 5
returnsTrue
,5 < 3
returnsFalse
Greater Than or Equal To (>=
)
- Checks if the left operand is greater than or equal to the right operand.
- Example:
5 >= 5
returnsTrue
,3 >= 5
returnsFalse
Less Than or Equal To (<=
)
- Checks if the left operand is less than or equal to the right operand.
- Example:
3 <= 5
returnsTrue
,5 <= 3
returnsFalse
Following is example for reference.
x = 10
y = 5
print(x == y) # False
print(x != y) # True
print(x > y) # True
print(x < y) # False
print(x >= y) # True
print(x <= y) # False
age = 25
if age >= 18:
print("You are an adult.")
else:
print("You are a minor.")
Logical operators
Logical operators are used to combine multiple Boolean expressions. They are essential for creating more complex conditions in your code.
Here are the main logical operators in Python:
and
: Returns True
if both operands are True
, otherwise returns False
.
True and True # True
True and False # False
False and True # False
False and False # False
or
: Returns True
if at least one operand is True
, otherwise returns False
.
True or True # True
True or False # True
False or True # True
False or False # False
not
: Inverts the truth value of the operand.
not True # False
not False # True
Example
# and example
age = 25
has_driver_license = True
if age >= 18 and has_driver_license:
print("You are eligible to drive.")
# or example
is_raining = True
is_sunny = False
if is_raining or is_sunny:
print("It's either raining or sunny.")
Order of Operations
Logical operators have an order of precedence:
not
and
or
You can use parentheses to override the default order of operations:
result = not (True and False) # Result will be True
Control Flow
Control flow statements allow you to alter the order in which your Python code is executed. They give you the power to make decisions and repeat actions based on specific conditions.
if
, elif
, else
:Used to make decisions based on conditions.
Syntax:
if condition1:
# Code to execute if condition1 is True
elif condition2:
# Code to execute if condition1 is False and condition2 is True
else:
# Code to execute if all previous conditions are False
Example:
age = 20
if age < 18:
print("You are a minor.")
elif age >= 18 and age < 65:
print("You are an adult.")
else:
print("You are a senior.") 1
ternary operator
In Python, the ternary operator is a concise way to write conditional expressions. It allows you to evaluate a condition and return one of two values based on whether the condition is True
or False
. The syntax is:
value_if_true if condition else value_if_false
Example 1: Basic Usage
x = 10
y = 20
# Use the ternary operator to find the maximum of two numbers
max_value = x if x > y else y
print("Max value:", max_value)
Example 2: Ternary Operator with Lists
numbers = [1, 2, 3, 4, 5]
# Use ternary operator to filter even numbers
filtered_numbers = [x if x % 2 == 0 else "Odd" for x in numbers]
print("Filtered list:", filtered_numbers)
# Filtered list: ['Odd', 2, 'Odd', 4, 'Odd']
for loop
Used to iterate over a sequence of elements (like lists, tuples, strings, or ranges).
Syntax
for item in sequence:
# Code to execute for each item
Example
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
while
Loop: Used to repeat a block of code as long as a condition is True.
Syntax
while condition:
# Code to execute as long as condition is True
Example
count = 0
while count < 5:
print(count)
count = count + 1
break
: Exits the loop immediately.
continue
: Skips the current iteration of the loop and moves to the next one.
for i in range(10):
if i == 5:
break # Exit the loop when i reaches 5
if i % 2 == 0:
continue # Skip even numbers
print(i)
Data Structures
Data structures are fundamental to organizing and storing data effectively in your programs. Python offers several built-in data structures:
Lists
- Ordered Collection: Elements are stored in a specific order.
- Mutable: You can change the elements of a list after it’s created.
- Syntax:
my_list = [element1, element2, ...]
fruits = ["apple", "banana", "cherry"]
numbers = [1, 2, 3, 4, 5]
mixed_list = [10, "hello", True]
Key Operations:
- Accessing elements:
my_list[index]
(e.g.,fruits[0] # Accesses the first element
) - Slicing:
my_list[start:end]
(e.g.,fruits[1:3] # Accesses elements from index 1 to 2
) - Adding elements:
my_list.append()
,my_list.insert()
- Removing elements:
my_list.remove()
,my_list.pop()
- Modifying elements:
my_list[index] = new_value
Tuples
Similar to lists, but immutable.
Syntax: my_tuple = (element1, element2, ...)
coordinates = (10, 20)
days_of_week = ("Monday", "Tuesday", "Wednesday")
Key Characteristics:
- Once created, you cannot change the elements of a tuple.
- Used for representing data that should not be modified.
Dictionaries
Unordered collections of key-value pairs. You can add, remove, or modify key-value pairs.
Syntax: my_dict = {key1: value1, key2: value2, ...}
student = {"name": "Alice", "age": 25, "city": "New York"}
Key Operations:
- Accessing values:
my_dict[key]
- Adding key-value pairs:
my_dict[new_key] = new_value
- Removing key-value pairs:
del my_dict[key]
Sets
Unordered collections of unique elements. You can add or remove elements.
Syntax: my_set = {element1, element2, ...}
unique_numbers = {1, 2, 3, 3, 4, 4} # Set will contain only 1, 2, 3, 4
Key Operations:
- Checking for membership:
element in my_set
- Set operations:
union()
,intersection()
,difference()
set1 = {1, 2, 3}
set2 = {3, 4, 5}
# union example
union_set = set1.union(set2) # or set1 | set2
print(union_set) # Output: {1, 2, 3, 4, 5}
# intersection example
intersection_set = set1.intersection(set2) # or set1 & set2
print(intersection_set) # Output: {3}
# difference example
difference_set = set1.difference(set2) # or set1 - set2
print(difference_set) # Output: {1, 2}
Functions
In Python, a function is a block of reusable code that performs a specific task. It helps to organize your code, improve readability, and avoid code duplication.
Defining a Function:
You define a function using the def
keyword followed by the function name, parentheses for parameters (if any), and a colon. The 1 code block within the function is indented.
def greet(name):
"""This function greets the person passed in as a parameter."""
print("Hello, " + name + "!")
Calling a Function:
To use a function, you “call” it by using its name followed by parentheses.
greet("Alice") # Output: Hello, Alice!
Parameters and Arguments:
- Parameters: Variables defined within the parentheses of a function definition. They act as placeholders for values that will be passed to the function.
- Arguments: The actual values that are passed to a function when it’s called.
def add(x, y):
"""This function adds two numbers."""
return x + y
result = add(5, 3) # 5 and 3 are arguments
print(result) # Output: 8
Return Statement:
The return
statement specifies the value that a function should return. If no return
statement is used, the function will return None
by default.
def square(x):
return x * x
result = square(4)
print(result) # Output: 16
Function Scope: Variables defined within a function are local to that function and cannot be accessed outside of it.
Global Variables: Variables defined outside of any function are global and can be accessed from anywhere in the code.
Default Arguments: You can provide default values for function parameters.
def greet(name, greeting="Hello"):
print(greeting + ", " + name + "!")
greet("Bob") # Output: Hello, Bob!
greet("Alice", "Hi") # Output: Hi, Alice!
Lambda Functions (Anonymous Functions)
In Python, lambda functions are small, anonymous functions that are defined using the lambda
keyword. They are often used for simple, one-off operations.
Syntax:
lambda arguments: expression
lambda
: The keyword that signifies the start of a lambda function.arguments
: The parameters the function accepts.expression
: The single expression that the function evaluates and returns.
# Define a lambda function to square a number
square = lambda x: x * x
result = square(5) # Calculate 5 squared
print(result) # Output: 25
Common Use Cases:
map()
function: Applying a function to each element of an iterable.
numbers = [1, 2, 3, 4]
squared_numbers = list(map(lambda x: x * x, numbers))
print(squared_numbers) # Output: [1, 4, 9, 16]
filter()
function: Filtering elements from an iterable based on a condition.
numbers = [1, 2, 3, 4, 5]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # Output: [2, 4]
sorted()
function: Sorting a list based on a custom key.
names = ["Alice", "bob", "Charlie"]
sorted_names = sorted(names, key=lambda x: x.lower())
print(sorted_names) # Output: ['Alice', 'bob', 'Charlie']
main method
In Python, there’s no strict equivalent to the main()
method as you might find in languages like Java or C++. However, you can achieve a similar effect using a few common approaches:
Using if __name__ == "__main__":
This is the most common and recommended way to define the entry point of your Python script.
def main():
# Code to be executed when the script is run directly
if __name__ == "__main__":
main()
__name__
is a special variable that holds the name of the current module.- When you run a Python script directly (e.g.,
python my_script.py
),__name__
is set to"__main__"
. - If the script is imported as a module in another script,
__name__
will be set to the module's name. - This allows you to write reusable code that can be both executed directly and imported as a module.
Object-Oriented Programming (OOP)
OOP is a programming paradigm that organizes code around “objects” that encapsulate data (attributes) and methods (functions) that operate on that data.
Classes: A blueprint or template for creating objects. Defines the attributes (data) and methods (behaviors) that objects of that class will have.
Objects: Instances of a class. Each object has its own set of attribute values
Attributes: Characteristics or properties of an object. Represented by variables within a class.
Methods: Functions that belong to a class. Define the actions or behaviors that objects of the class can perform.
Example
class Dog:
"""A simple Dog class"""
def __init__(self, name, breed): # Constructor (special method)
self.name = name
self.breed = breed
def bark(self):
print("Woof!")
def display_info(self):
print(f"Name: {self.name}")
print(f"Breed: {self.breed}")
# Create objects (instances) of the Dog class
my_dog = Dog("Buddy", "Golden Retriever")
your_dog = Dog("Coco", "Poodle")
# Access attributes
print(my_dog.name) # Output: Buddy
# Call methods
my_dog.bark() # Output: Woof!
your_dog.display_info()
Inheritance: Creating subclasses and inheriting properties from parent classes.
super()
: The super().__init__(name)
call in the Dog
class's constructor invokes the constructor of the parent class to initialize the name
attribute.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print("Generic animal sound")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # Call the parent class's constructor
self.breed = breed
def speak(self):
print("Woof!")
class Cat(Animal):
def speak(self):
print("Meow!")
# Create objects
my_dog = Dog("Buddy", "Golden Retriever")
my_cat = Cat("Whiskers")
# Access attributes and call methods
print(my_dog.name) # Output: Buddy
print(my_dog.breed) # Output: Golden Retriever
my_dog.speak() # Output: Woof!
print(my_cat.name) # Output: Whiskers
my_cat.speak() # Output: Meow!
Polymorphism
Polymorphism is a fundamental concept in Object-Oriented Programming (OOP). It allows objects of different classes to be treated as objects of a common type. This means the same method can be called on different objects, and the specific behavior will vary based on the object’s class.
class Animal:
def sound(self):
print("Generic animal sound")
class Dog(Animal):
def sound(self):
print("Woof!")
class Cat(Animal):
def sound(self):
print("Meow!")
def make_sound(animal):
animal.sound()
dog = Dog()
cat = Cat()
make_sound(dog) # Output: Woof!
make_sound(cat) # Output: Meow!
Duck Typing
- Python’s dynamic nature allows for a flexible form of polymorphism known as “duck typing.”
- If an object “walks like a duck and quacks like a duck,” then it is treated as a duck.
- It focuses on the object’s behavior rather than its specific class.
def fly(bird):
bird.fly()
class Duck:
def fly(self):
print("Duck is flying")
class Airplane:
def fly(self):
print("Airplane is flying")
duck = Duck()
airplane = Airplane()
fly(duck) # Output: Duck is flying
fly(airplane) # Output: Airplane is flying
Encapsulation
Data Hiding: Making attributes private using a single underscore (_
) prefix. This indicates that the attribute is intended for internal use and should not be accessed directly from outside the class.
class Employee:
def __init__(self, name, salary):
self._name = name # Private attribute
self._salary = salary
def get_name(self):
return self._name
def get_salary(self):
return self._salary
Public Interface: You provide controlled access to the object’s data through public methods (also called getters and setters).
class Employee:
def __init__(self, name, salary):
self._name = name
self._salary = salary
def get_name(self):
return self._name
def set_name(self, new_name):
self._name = new_name
def get_salary(self):
return self._salary
def set_salary(self, new_salary):
if new_salary >= 0: # Validate salary value
self._salary = new_salary
else:
print("Invalid salary.")
Private Methods
Prefixing with double underscores (__): This is the convention for indicating a method as private. For example: __private_method(self)
class MyClass:
def __init__(self):
self.__private_var = 10
def __private_method(self):
print("This is a private method.")
def public_method(self):
self.__private_method()
# Accessing private members
my_object = MyClass()
# my_object.__private_var # This will likely raise an AttributeError
# my_object.__private_method() # This will likely raise an AttributeError
my_object.public_method() # This will work, as __private_method is called within the class
Name Mangling: When you define a method with a double underscore prefix (e.g., __private_method
), Python performs "name mangling". It automatically changes the name of the method to include the class name, making it harder to access from outside the class. For example, if you have a class named MyClass
, the method __private_method
will be renamed to _MyClass__private_method
.
Not Truly Private: While name mangling makes it less likely to accidentally access private methods from outside the class, it’s not a foolproof mechanism. Determined users could still access them if they really wanted to.
Error and exception handling
In Python, exceptions are events that occur during the execution of a program that disrupt the normal flow of the program. They can arise from various sources, such as:
- Runtime errors: Incorrect input, invalid operations, resource exhaustion, etc.
- Logical errors: Issues in the program’s logic that lead to unexpected behavior.
Error and Exception Handling in Python
In Python, exceptions are events that occur during the execution of a program that disrupt the normal flow of the program. They can arise from various sources, such as:
- Runtime errors: Incorrect input, invalid operations, resource exhaustion, etc.
- Logical errors: Issues in the program’s logic that lead to unexpected behavior.
Handling Exceptions with try...except
try
block: Contains the code that might raise an exception.except
block: Contains the code that will be executed if an exception occurs. You can specify the type of exception to catch.else
block: (Optional) Contains code that will be executed if no exceptions occur in thetry
block.finally
block: (Optional) Contains code that will be executed regardless of whether an exception occurred or not.
try:
num1 = int(input("Enter the first number: "))
num2 = int(input("Enter the second number: "))
result = num1 / num2
print("Result:", result)
except ZeroDivisionError:
print("Error: Division by zero!")
except ValueError:
print("Error: Invalid input. Please enter numbers only.")
else:
print("Division successful.")
finally:
print("Execution complete.")
Common Built-in Exceptions:
ZeroDivisionError
: Raised when dividing by zero.ValueError
: Raised when an operation or function receives an argument of an inappropriate type.TypeError
: Raised when an operation or function is applied to an object of an inappropriate type.IndexError
: Raised when trying to access a list or tuple index that is out of range.KeyError
: Raised when trying to access a dictionary key that does not exist.
Raising Exceptions (Manually)
You can raise exceptions manually using the raise
keyword:
if age < 0:
raise ValueError("Age cannot be negative.")
Modules and Packages
Modules
What is a Module?
- A Python module is a single file containing Python code (functions, classes, variables, etc.).
- It allows you to organize your code into reusable units.
- Example:
math
module (for mathematical functions likesin
,cos
,sqrt
),random
module (for generating random numbers)
Importing Modules
Use the import
statement to bring the module into your current script.
import math
result = math.sqrt(25)
print(result) # Output: 5.0
Import specific functions/classes:
from math import sqrt, pi
result = sqrt(16)
print(pi)
Import with an alias:
import math as m
result = m.sin(math.pi/2)
print(result)
Packages
What is a Package?
- A package is a collection of related modules organized in a directory.
- It helps to structure large projects and avoid namespace conflicts.
- A package directory must contain a special file named
__init__.py
(can be empty).
Importing from Packages:
import my_package.my_module
my_package.my_module.my_function()
We can also import as below.
from my_package import my_module
from my_package.my_module import my_function
__name__
variable: This special variable holds the name of the current module. It's often used to determine if a script is being run directly or imported as a module:
Following is example of module.
# my_math_module.py
def add(x, y):
"""
This function adds two numbers.
Args:
x: The first number.
y: The second number.
Returns:
The sum of x and y.
"""
return x + y
def subtract(x, y):
"""
This function subtracts the second number from the first.
Args:
x: The first number.
y: The second number.
Returns:
The difference of x and y.
"""
return x - y
Use this module
import my_math_module
result1 = my_math_module.add(5, 3) # Result: 8
result2 = my_math_module.subtract(5, 3) # Result: 2
print(result1)
print(result2)
import module from different directory
Use sys.path.append()
This method adds the directory containing the module to Python’s search path.
import sys
sys.path.append('/path/to/your/module/directory')
import your_module
Using PYTHONPATH
Environment Variable. This method permanently adds the directory to Python’s search path.
export PYTHONPATH="$PYTHONPATH:/path/to/your/module/directory"
Using Relative Imports (for packages): If your module is part of a package, you can use relative imports.
from . import my_module # Import from the same directory
from ..sub_package import my_module # Import from the parent directory
string
In Python, a string is a sequence of characters enclosed within either single quotes ('
) or double quotes ("
).
my_string1 = "This is a string."
my_string2 = 'Another string.'
Accessing Characters:
- Strings are indexed, starting from 0.
- You can access individual characters using square brackets
[]
.
my_string = "Hello"
first_char = my_string[0] # Accesses the first character ('H')
last_char = my_string[-1] # Accesses the last character ('o')
Slicing Strings:
my_string = "Python is awesome!"
substring = my_string[7:11] # Extracts "is aw"
String Concatenation:
first_name = "John"
last_name = "Doe"
full_name = first_name + " " + last_name # Result: "John Doe"
String Methods:
Python provides many built-in methods for string manipulation:
upper()
: Converts the string to uppercase.lower()
: Converts the string to lowercase.strip()
: Removes leading and trailing whitespace.split()
: Splits the string into a list of substrings.replace()
: Replaces occurrences of one substring with another.find()
: Returns the index of the first occurrence of a substring.- and many more!
my_string = "Hello, world!"
print(my_string.upper()) # Output: HELLO, WORLD!
print(my_string.lower()) # Output: hello, world!
my_string = " Hello "
print(my_string) # Output: Hello
print(my_string.strip()) # Output: Hello
sentence = "This is a sentence."
words = sentence.split() # Splits by whitespace by default
print(words) # Output: ['This', 'is', 'a', 'sentence.']
words = sentence.split(' ') # Explicitly split by spaces
print(words) # Output: ['This', 'is', 'a', 'sentence.']
text = "Hello, world!"
new_text = text.replace("world", "everyone")
print(new_text) # Output: Hello, everyone!
text = "Python is awesome!"
index = text.find("is")
print(index) # Output: 7 (index of the first occurrence of "is")
words = ["This", "is", "a", "list", "of", "words"]
sentence = " ".join(words)
print(sentence) # Output: This is a list of words
text = "This is a test string."
count_of_is = text.count("is")
print(count_of_is) # Output: 2
String Formatting:
Use f-strings (formatted string literals) for easy string interpolation.
name = "Alice"
age = 30
message = f"Hello, {name}! You are {age} years old."
Happy learning python!!!