Python for Programmers

A guide for the ones who never tried it

March 2025

Introduction

Why this guide?

  • For developers with Java/C# experience
  • Focus on the bigger picture
  • Understand the "why" behind Python design
  • Accelerate your Python learning journey
  • I wrote a guide guide btw, what should we do?..

What IS Python?

  • High-level, interpreted programming language
  • Created by Guido van Rossum in 1991
  • Emphasized readability and simplicity
  • De-facto standard for scientific fields, including AI
  • Well-suited for scripts and complete projects
  • Easy to learn, challenging to master
  • Supports multiple programming paradigms

The Philosophy of Python

Zen of Python (import this)

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
...

Hello World

No boilerplate, always straightforward:

print("Hello, World!")

Basic Data Types

# Variables (no type declarations)
name = "Python"  # str
age = 30  # int
price = 19.99  # float
is_available = True  # bool

# Type checking
print(type(name))  # <class 'str'>
print(isinstance(name, str))  # True => Safer!

Strong, Dynamic Typing

Python is dynamically typed but strongly typed

# Python - Raises TypeError
>>> a = 42
>>> b = "answer"
>>> a + b
Traceback (most recent call last):
TypeError: unsupported operand type(s) for +: 'int' and 'str'
// JavaScript - Implicit conversion
> a = 42
42
> b = 'answer'
'answer'
> a + b
'42answer'

Collections

Container data types to store multiple items

  • Lists (mutable)
  • Tuples (immutable)
  • Dictionaries (key-value pairs)
  • Sets (unique items)

Lists

Mutable arrays (not linked lists)

l = ["a", "b", "c"]
l.append("d")  # Add one element
l.extend(["e", "f"])  # Add multiple elements
print(l)       # ['a', 'b', 'c', 'd', 'e', 'f']
print(l[0])    # 'a'
print(l[1:3])  # ['b', 'c'] - Range indexing
print(l[-1])   # 'f' - Negative indexing

Tuples

Like lists but immutable

t = (1, 2, 3)  # Defines a 3 elements tuple
print(t)       # (1, 2, 3)
t = (1,)       # Defines a 1 element tuple
print(t)       # (1,)
t = 1, 2, 3    # Defines the same 3 elements tuple
print(t)       # (1, 2, 3)
t = 1,         # Valid 1 element tuple
print(t)       # (1,)

Dictionaries

Key-value pairs like HashMap (O(1) average operations)

AGE = "age"
user = {
    "name": "Alice",
    AGE: 30,  # Variable as key name
    "languages": ["Python", "Java"],
}
print(user["name"])  # prints: Alice

Dictionaries - get vs []

user = {}
>>> user["a"]
Traceback (most recent call last):
KeyError: "a"
>>> print(a.get(3))
None
>>> print(a.get(3, 42))
42

Sets

Hash table without values (unique elements)

unique_numbers = {1, 2, 3, 3, 4}  # Will contain 1, 2, 3, 4
print(1 in unique_numbers)  # True in nearly constant time

More collections in collections module

Control Flow

If statements

x = 10
if x > 5:
    print("x is greater than 5")
elif x == 5:
    print("x equals 5")
else:
    print("x is less than 5")

Ternary expressions

x = 10
print("greater" if x > 5 else "equals" if x == 5 else "less")

For Loops

languages = ["french", "english", "italian"]
for language in languages:
    print(language)

Range-based loops

for i in range(5):  # 0 to 4
    print(i)

Inline For

# List comprehension
[x for x in range(10)]  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# Dictionary comprehension
{k: v for k, v in pairs}  # Creates a dictionary

# Set comprehension
{x for x in items}  # Creates a set

# Generator expression
(x for x in range(10))  # Creates a generator
# Dict comprehension example
the_dict = {"a": 3, "b": 4}
print([k * 2 for k in the_dict.keys()])  # ["aa", "bb"]
print([v * 2 for v in the_dict.values()])  # [6, 8]
print({k * 2: v * 2 for k, v in the_dict.items()})
# {'aa': 6, 'bb': 8}

Conditional

# Creating lists with loop logic
squares = [x * x for x in range(10)]
# With conditions
even_squares = [x * x for x in range(10) if x % 2 == 0]
print(even_squares)  # [0, 4, 16, 36, 64]

While Loops

count = 0
while count < 5:
    print(count)
    count += 1

Functions

# Defining functions
def greet(name, greeting="Hello"):
    """Greet a person with a custom greeting."""  # Docstring
    return f"{greeting}, {name}!"

# Calling functions
print(greet("Java Developer"))  # Default greeting
print(greet("Python Novice", "Welcome"))  # Custom greeting

# Variable arguments
def sum_all(*numbers):
    return sum(numbers)

print(sum_all(1, 2, 3, 4))  # 10

Decorators

Modify behavior of functions or classes without changing source code

# Basic decorator example
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Run before the function is called.")
        result = func(*args, **kwargs)
        print("Run after the function is called.")
        return result
    return wrapper

@my_decorator  # <==== say_hello = my_decorator(say_hello)
def say_hello(name):
    return f"Hello, {name}!"
print(say_hello("Python Developer"))

Decorators with Arguments

def repeat(n=1):
    def decorator(func):
        def wrapper(*args, **kwargs):
            result = None
            for _ in range(n):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def greet(name):  # This prints "Hello, World!" three times
    print(f"Hello, {name}!")

Common uses: authentication, logging, caching, timing, validation...

Classes and Objects

class Person:
    species = "Human"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def introduce(self):
        return (
            f"Hi, I'm {self.name} "
            f"and I'm {self.age} years old."
        )

Classes and Objects

@staticmethod
def get_species_info_hardcoded():
    return "Humans are social beings."

@classmethod
def get_species_info_from_class(cls):
    return f"{cls.species} are social beings."

Classes and Objects

alice = Person("Alice", 30)
print(alice.introduce())
print(Person.get_species_info_hardcoded())
print(Person.get_species_info_from_class())

Inheritance

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

    def speak(self):
        return "Some sound"

class Dog(Animal):
    def speak(self):
        return "Woof!"

Inheritance

# Create an instance of the subclass
dog = Dog("Rex")
print(dog.name)
print(dog.speak())

# Multiple inheritance
class Swimmer:
    def swim(self):
        return "Swimming"

class Duck(Animal, Swimmer):
    def speak(self):
        return "Quack!"

Abstract Classes

from abc import ABC, abstractmethod

class Animal(ABC):
    @abstractmethod
    def make_sound(self):
        """This method must be implemented by subclasses"""
        pass

    def eat(self):
        print("Eating...")

class Dog(Animal):
    def make_sound(self):
        return "Woof!"

Abstract Classes

# This works
dog = Dog()
print(dog.make_sound())  # Woof!

# This would raise TypeError
# animal = Animal()

Lambda Functions

Anonymous single-expression functions

add = lambda a, b: a + b
print(add(5, 3))  # 8

# Useful with higher-order functions
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
print(squares)  # [1, 4, 9, 16, 25]

Exception Handling

class SpecificKindOfValueError(ValueError):
      """Defines an Exception inheriting from ValueError"""
      pass

Exception Handling

try:
    do_something()
except SpecificKindOfValueError:
    print("Here, handle SpecificKindOfValueError")
except ValueError:
    print("Not a valid number")
except (TypeError, KeyError):
    print("Type or key error occurred")
except Exception as e:
    print(f"Other error: {e}")
else:
    print("No exceptions occurred")
finally:
    print("This always executes")

Modules and Imports

# Single import
import math
print(math.sqrt(16))  # 4.0

# Import specific functions
from datetime import datetime
print(datetime.now())

# Import with alias
import numpy as np
arr = np.array([1, 2, 3])

Context Managers

Ensure specific logic executes before and after your code

# File handling (automatically closes file)
with open("example.txt", "w") as file:
    file.write("Hello, Python!")

Asynchronicity

Using async/await for concurrent operations

# Core concepts (sample code - not for execution)
result = await some_coroutine()

async def my_async_function():
    pass

results = await asyncio.gather(coro1(), coro2(), coro3())

task = asyncio.create_task(some_coroutine())

async for item in async_iterable:
    process(item)

Asynchronicity

Entering async context

# Run coroutine from non-async context
asyncio.run(main_coroutine())

coro = main_coroutine(a, b)  # Coroutine with parameters
print(coro)  # <coroutine object coro at 0x7f1bcc2fb940>
asyncio.run(coro)  # Pass coroutine between calls

Consider Trio for better async management

Python Downsides

  • Performance considerations
    • Interpreted with runtime type checking
    • Global Interpreter Lock (GIL) limits multithreading
    • No tail call optimization
      • Recursive functions have limited depth
      • May need iterative solutions for deep recursion
    • Rarely matters for most applications
    • Performance-critical code can use C/C++/Rust extensions

Python Ecosystem

Tooling

  • pyproject.toml: Standard project configuration
  • Package Management:
    • pip: Package installer
    • venv: Virtual environments
    • uv: Fast modern alternative from astral.sh
  • Typing: ty (astral.sh), replaces mypy
  • Linting: ruff (astral.sh), replaces most other tools

Type Hints

def greeting(name: str) -> str:
    return f"Hello, {name}"

age: int = 30

# Types aren't enforced at runtime
a: int = "0"  # No error
print(type(a))  # <class 'str'>

Benefits: Better code documentation, IDE support, static checking

General Conventions

  • PEP 8: Official style guide (naming, indentation, etc.)
  • Pythonic Code: Idiomatic patterns (list comprehensions, context managers)
  • Duck Typing: "If it walks like a duck and quacks like a duck, it's a duck"

Underscore Conventions

  • value: Regular public attribute/method
  • _value: "Private by convention" (not enforced)
  • __value: Name mangling (becomes _ClassName__value)
  • __value__: Special methods controlled by Python (magic/dunder methods)
  • value_: Avoid conflicts with Python keywords

Learning Python with AI

Claude (Anthropic) is excellent for learning Python concepts

Example Questions:

  • "What is the difference between Python iterator, iterable, and generator?"
  • "What is a Python metaclass?"
  • "Tell me about an advanced Python concept I may not know."
  • "Is there a more pythonic way to write this?"

Further Learning Resources

Further Learning Resources

Thank you for listening

Please give honest feedback!