Python Cheatsheet
Classes and OOP
Use this Python reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Defining a Class
class Dog: # Class variable — shared by all instances species = "Canis lupus familiaris" # Constructor def __init__(self, name: str, age: int): self.name = name # instance variable self.age = age # Instance method def bark(self): return f"{self.name} says woof!" def __repr__(self): return f"Dog(name={self.name!r}, age={self.age!r})" def __str__(self): return f"{self.name} ({self.age} years)" # Usage dog = Dog("Rex", 3) dog.name # "Rex" dog.bark() # "Rex says woof!" str(dog) # "Rex (3 years)" repr(dog) # "Dog(name='Rex', age=3)" Dog.species # "Canis lupus familiaris"
Inheritance
class Animal: def __init__(self, name): self.name = name def speak(self): raise NotImplementedError class Dog(Animal): def speak(self): return "Woof!" class Cat(Animal): def speak(self): return "Meow!" # super() class Puppy(Dog): def __init__(self, name, toy): super().__init__(name) # call parent __init__ self.toy = toy def speak(self): return super().speak() + " (puppy)" # Multiple inheritance class A: def method(self): return "A" class B(A): def method(self): return "B" class C(A): def method(self): return "C" class D(B, C): # MRO: D → B → C → A pass D().method() # "B" (follows MRO) D.__mro__ # (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)
Class Methods, Static Methods, Properties
class Circle: PI = 3.14159 def __init__(self, radius): self._radius = radius # Instance method — first arg is the instance def area(self): return self.PI * self._radius ** 2 # Class method — first arg is the class @classmethod def from_diameter(cls, diameter): return cls(diameter / 2) # alternative constructor # Static method — no implicit first argument @staticmethod def is_valid_radius(r): return r > 0 # Property — computed attribute with getter/setter/deleter @property def radius(self): return self._radius @radius.setter def radius(self, value): if value < 0: raise ValueError("radius cannot be negative") self._radius = value @radius.deleter def radius(self): del self._radius # Usage c = Circle(5) c.area() # 78.53... c.radius # 5 (calls getter) c.radius = 10 # calls setter del c.radius # calls deleter Circle.from_diameter(10) # Circle(5.0) Circle.is_valid_radius(-1) # False
Special (Dunder) Methods
Object Lifecycle
| Method | Called when |
|---|---|
__new__(cls, ...) | Creating the instance (before __init__) |
__init__(self, ...) | Initializing the instance |
__del__(self) | Object is garbage collected |
String Representation
| Method | Called when |
|---|---|
__repr__(self) | repr(obj), fallback for str() |
__str__(self) | str(obj), print(obj) |
__format__(self, spec) | format(obj, spec), f"{obj:spec}" |
__bytes__(self) | bytes(obj) |
Comparison
| Method | Operator |
|---|---|
__eq__(self, other) | == |
__ne__(self, other) | != (auto-derived from __eq__) |
__lt__(self, other) | < |
__le__(self, other) | <= |
__gt__(self, other) | > |
__ge__(self, other) | >= |
__hash__(self) | hash(obj), dict/set key |
If you define
__eq__, Python sets__hash__toNone(unhashable) unless you also define it.
Arithmetic
| Method | Operator | Reflected |
|---|---|---|
__add__(self, other) | + | __radd__ |
__sub__(self, other) | - | __rsub__ |
__mul__(self, other) | * | __rmul__ |
__truediv__(self, other) | / | __rtruediv__ |
__floordiv__(self, other) | // | __rfloordiv__ |
__mod__(self, other) | % | __rmod__ |
__pow__(self, other) | ** | __rpow__ |
__neg__(self) | unary - | |
__pos__(self) | unary + | |
__abs__(self) | abs() |
In-place: __iadd__, __isub__, __imul__, etc. (+=, -=, *=).
Container / Sequence Protocol
| Method | Called when |
|---|---|
__len__(self) | len(obj) |
__getitem__(self, key) | obj[key] |
__setitem__(self, key, val) | obj[key] = val |
__delitem__(self, key) | del obj[key] |
__contains__(self, item) | item in obj |
__iter__(self) | iter(obj), for x in obj |
__next__(self) | next(obj) — implement with __iter__ |
__reversed__(self) | reversed(obj) |
__missing__(self, key) | dict subclass: key not found |
Context Manager
class ManagedResource: def __enter__(self): self.resource = acquire() return self.resource # bound to `as` variable def __exit__(self, exc_type, exc_val, exc_tb): release(self.resource) return False # True would suppress exceptions with ManagedResource() as r: use(r)
Callable and Attribute Access
| Method | Called when |
|---|---|
__call__(self, ...) | obj(...) — makes instance callable |
__getattr__(self, name) | attribute not found normally |
__getattribute__(self, name) | any attribute access (use carefully) |
__setattr__(self, name, val) | obj.name = val |
__delattr__(self, name) | del obj.name |
__dir__(self) | dir(obj) |
dataclasses
from dataclasses import dataclass, field @dataclass class Point: x: float y: float z: float = 0.0 p = Point(1.0, 2.0) p.x # 1.0 repr(p) # "Point(x=1.0, y=2.0, z=0.0)" # Mutable defaults must use field() @dataclass class Config: tags: list[str] = field(default_factory=list) metadata: dict = field(default_factory=dict) # Options @dataclass(frozen=True) # immutable (also hashable) @dataclass(order=True) # generates __lt__, __le__, etc. @dataclass(eq=False) # skip __eq__ @dataclass(slots=True) # use __slots__ (Python 3.10+) # post_init @dataclass class Rectangle: width: float height: float area: float = field(init=False) def __post_init__(self): self.area = self.width * self.height
Abstract Base Classes
from abc import ABC, abstractmethod class Shape(ABC): @abstractmethod def area(self) -> float: ... @abstractmethod def perimeter(self) -> float: ... # Concrete method in abstract class is fine def describe(self): return f"Area: {self.area()}, Perimeter: {self.perimeter()}" class Circle(Shape): def __init__(self, r): self.r = r def area(self): return 3.14159 * self.r ** 2 def perimeter(self): return 2 * 3.14159 * self.r # Shape() → TypeError: Can't instantiate abstract class
__slots__
Restrict instance attributes, reduce memory, speed up attribute access.
class Point: __slots__ = ("x", "y") # tuple or list of allowed attribute names def __init__(self, x, y): self.x = x self.y = y # p.z = 1 → AttributeError: 'Point' object has no attribute 'z' # vars(p) → AttributeError: no __dict__
Class Introspection
isinstance(obj, ClassName) # True if obj is instance of ClassName or subclass issubclass(Sub, Parent) # True if Sub is subclass of Parent type(obj) is ClassName # exact type check (no inheritance) type(obj).__name__ # class name as string obj.__class__ # same as type(obj) ClassName.__bases__ # direct parent classes ClassName.__mro__ # full MRO tuple ClassName.__dict__ # class namespace dict obj.__dict__ # instance attribute dict (if no __slots__) hasattr(obj, "method") getattr(obj, "method", default) setattr(obj, "attr", value) dir(obj) # all attribute names
Mixins
class SerializeMixin: def to_dict(self): return self.__dict__.copy() def to_json(self): import json return json.dumps(self.to_dict()) class LogMixin: def log(self, msg): print(f"[{self.__class__.__name__}] {msg}") class User(SerializeMixin, LogMixin): def __init__(self, name, email): self.name = name self.email = email u = User("Alice", "alice@example.com") u.to_dict() # {'name': 'Alice', 'email': 'alice@example.com'} u.log("hello") # [User] hello