Python Tutorial

Introduction to Python

Welcome to the comprehensive Python tutorial! Python is a high-level, interpreted, general-purpose programming language. Created by Guido van Rossum and first released in 1991, Python's design philosophy emphasizes code readability with its notable use of significant indentation.

What is Python?

Python is known for its simplicity and versatility. It is widely used in web development (Django, Flask), data science (NumPy, Pandas, Scikit-learn), artificial intelligence and machine learning, automation, scientific computing, and more. Its extensive libraries and frameworks make it a powerful tool for various applications.

Setting Up Your Development Environment

To start coding in Python, you'll need to install the Python interpreter and optionally a code editor or Integrated Development Environment (IDE).

  1. **Download Python:** Go to the official Python website and download the latest stable version for your operating system (Windows, macOS, Linux).
  2. **Installation:** Follow the installer instructions. **Important:** On Windows, make sure to check "Add Python to PATH" during installation.
  3. **Verify Installation:** Open your command prompt or terminal and type `python --version` (or `python3 --version` on some systems). You should see the installed Python version.
  4. **Choose an Editor/IDE:**
    • **VS Code:** A popular, lightweight, and highly customizable code editor. Download from code.visualstudio.com. Install the Python extension.
    • **PyCharm:** A dedicated and powerful IDE for Python development (Community Edition is free). Download from jetbrains.com/pycharm.
    • **Jupyter Notebook/Lab:** Excellent for data science and interactive computing. Install via `pip install jupyterlab`.

Your First Python Program: "Hello, World!"

Let's write the classic "Hello, World!" program. Save this code as `hello.py` and run it from your terminal using `python hello.py`.


# This is a single-line comment in Python
print("Hello, World!") # The print() function outputs text to the console
            

Explanation:


Python Fundamentals

Variables and Data Types

Variables are used to store data. Python is dynamically typed, meaning you don't declare the type explicitly; it's inferred at runtime.


# Numeric types
age = 30          # int (integer)
price = 19.99     # float (floating-point number)
complex_num = 1 + 2j # complex (complex number)

# String type
name = "Alice"    # str (string)
message = 'Hello, Python!' # Single or double quotes work

# Boolean type
is_active = True  # bool (Boolean, True or False)

# Collection types
my_list = [1, 2, "three"] # list (ordered, mutable, allows duplicates)
my_tuple = (10, 20, "thirty") # tuple (ordered, immutable, allows duplicates)
my_set = {1, 2, 3, 2} # set (unordered, mutable, no duplicates)
my_dict = {"name": "Bob", "age": 25} # dict (unordered, mutable, key-value pairs)

print(f"Name: {name}, Type: {type(name)}")
print(f"Age: {age}, Type: {type(age)}")
print(f"First element of list: {my_list[0]}")
print(f"Value for 'name' in dict: {my_dict['name']}")
            

Python's dynamic typing and rich set of built-in data structures are key features.

Operators

Operators perform operations on values and variables.


x = 10
y = 3

print(f"Addition: {x + y}")       # 13
print(f"Integer Division: {x // y}") # 3
print(f"Modulus: {x % y}")        # 1
print(f"Exponentiation: {x ** y}") # 1000

print(f"Is x equal to y? {x == y}") # False
print(f"Is x greater than y and x is positive? {x > y and x > 0}") # True
            

Control Flow

Control flow statements determine the order of execution. Python uses indentation for code blocks.

If-Elif-Else Statements


score = 85
if score >= 90:
    print("Grade: A")
elif score >= 80:
    print("Grade: B")
else:
    print("Grade: C or lower")
            

Loops (for, while)


# For loop
for i in range(5): # range(5) generates numbers from 0 to 4
    print(f"For loop iteration: {i}")

# While loop
count = 0
while count < 3:
    print(f"While loop iteration: {count}")
    count += 1

# Iterating over a list
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(f"Fruit: {fruit}")
            

Functions

Functions are reusable blocks of code that perform a specific task.


def greet(name):
    """This function greets the person passed in as a parameter."""
    print(f"Hello, {name}!")

def add_numbers(num1, num2):
    """This function returns the sum of two numbers."""
    return num1 + num2

greet("Bob") # Call the greet function
sum_result = add_numbers(15, 25)
print(f"Sum: {sum_result}") # Output: Sum: 40
            

Object-Oriented Programming (OOP) in Python

Python fully supports Object-Oriented Programming, allowing you to model real-world entities using classes and objects.

Classes and Objects

A **class** is a blueprint, and an **object** is an instance of that class.


class Dog:
    # Class attribute
    species = "Canis familiaris"

    # Constructor (initializer)
    def __init__(self, name, age):
        self.name = name # Instance attribute
        self.age = age   # Instance attribute

    # Instance method
    def bark(self):
        print(f"{self.name} says Woof!")

# Creating objects
my_dog = Dog("Buddy", 3)
your_dog = Dog("Lucy", 5)

print(f"My dog's name is {my_dog.name} and he is {my_dog.age} years old.")
my_dog.bark()
print(f"Lucy's species is {your_dog.species}.")
            

Inheritance

Inheritance allows a class (child) to inherit attributes and methods from another class (parent).


class Animal: # Parent class
    def __init__(self, name):
        self.name = name

    def speak(self):
        raise NotImplementedError("Subclass must implement abstract method")

class Cat(Animal): # Child class inheriting from Animal
    def __init__(self, name, breed):
        super().__init__(name) # Call parent constructor
        self.breed = breed

    def speak(self): # Overriding parent method
        print(f"{self.name} the {self.breed} meows.")

# Usage:
my_cat = Cat("Whiskers", "Siamese")
my_cat.speak() # Output: Whiskers the Siamese meows.
print(f"My cat's name is {my_cat.name}")
            

Polymorphism

Polymorphism means "many forms." It allows objects of different classes to be treated as objects of a common superclass, or by implementing a common interface (duck typing in Python).


class Bird:
    def fly(self):
        print("Bird is flying")

class Plane:
    def fly(self):
        print("Plane is flying")

def make_it_fly(obj):
    obj.fly()

# Usage:
make_it_fly(Bird())  # Output: Bird is flying
make_it_fly(Plane()) # Output: Plane is flying
            

Encapsulation

Encapsulation involves restricting direct access to some of an object's components. In Python, this is typically achieved by convention (using a single underscore `_` for protected and double underscore `__` for private-like attributes, though they are still accessible).


class BankAccount:
    def __init__(self, initial_balance):
        self.__balance = initial_balance # "Private" attribute by convention

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(f"Deposited: {amount}. New balance: {self.__balance}")
        else:
            print("Deposit amount must be positive.")

    def get_balance(self): # Public method to access balance
        return self.__balance

# Usage:
account = BankAccount(1000)
account.deposit(500)
print(f"Current balance: {account.get_balance()}")
# print(account.__balance) # This would raise an AttributeError (name mangling)
# print(account._BankAccount__balance) # This would work, showing it's not truly private
            

Abstraction

Abstraction means hiding the complex implementation details and showing only the essential features. In Python, this can be achieved using abstract base classes (`abc` module) or simply by defining methods that subclasses are expected to implement (duck typing).


from abc import ABC, abstractmethod

class Shape(ABC): # Abstract Base Class
    @abstractmethod
    def area(self):
        pass # Abstract method, must be implemented by subclasses

    def describe(self):
        print("This is a geometric shape.")

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self): # Implementation of the abstract method
        return 3.14159 * self.radius ** 2

# Usage:
circle = Circle(5)
print(f"Area of Circle: {circle.area()}")
circle.describe()
# shape = Shape() # This would raise a TypeError
            

Key Python Features

List Comprehensions

Provide a concise way to create lists. It consists of brackets containing an expression followed by a `for` clause, then zero or more `for` or `if` clauses.


# Create a list of squares
squares = [x**2 for x in range(10)]
print(f"Squares: {squares}") # Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# Filter and transform elements
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(f"Even Squares: {even_squares}") # Output: [0, 4, 16, 36, 64]
            

Error Handling (try-except)

Python uses `try`, `except`, `else`, and `finally` blocks to handle errors gracefully.


try:
    result = 10 / 0 # This will cause a ZeroDivisionError
except ZeroDivisionError:
    print("Error: Cannot divide by zero!")
except TypeError:
    print("Error: Type mismatch!")
else:
    print(f"Result: {result}")
finally:
    print("Execution finished.")

print("\n--- Another example ---")
try:
    num = int("abc") # This will cause a ValueError
except ValueError:
    print("Error: Invalid conversion to integer!")
            

Modules and Packages

**Modules** are Python files (`.py`) containing code. **Packages** are directories containing multiple modules and a special `__init__.py` file, used to organize related modules.


# Example of using a built-in module
import math
print(f"Pi: {math.pi}")
print(f"Square root of 16: {math.sqrt(16)}")

# From a module, import specific functions
from datetime import datetime
print(f"Current date and time: {datetime.now()}")

# To create your own module:
# 1. Create a file named 'my_module.py' with content:
#    def say_hello(name):
#        return f"Hello, {name} from my_module!"
#
# 2. In another file (in the same directory or accessible via PATH):
#    import my_module
#    print(my_module.say_hello("World"))
            

Decorators

Decorators allow you to modify or extend the behavior of functions or methods without permanently modifying their source code. They are essentially functions that take another function as an argument and return a new function.


def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Something is happening before the function is called.")
        result = func(*args, **kwargs)
        print("Something is happening after the function is called.")
        return result
    return wrapper

@my_decorator
def say_hello(name):
    print(f"Hello, {name}!")
    return f"Greeting for {name}"

# Usage:
returned_value = say_hello("Alice")
print(f"Returned value: {returned_value}")
# Output:
# Something is happening before the function is called.
# Hello, Alice!
# Something is happening after the function is called.
# Returned value: Greeting for Alice
            

Conclusion and Next Steps

This tutorial has provided a solid introduction to Python programming, covering its fundamentals, OOP concepts, and some powerful features. Python's ease of use and vast ecosystem make it an excellent choice for a wide range of applications. To further your Python journey:

Happy coding!