Python Reference Guide
Lambda, OOP & Exception Handling
3. LAMBDA
SYNTAX
lambda arguments : expression
add = lambda x, y: x + y
RULES: one expression only, always returns result, x = item not index
3 TOOLS
• map() → transform every item → wrap with list()
• filter() → keep matching items → wrap with list()
• sorted() → sort by custom rule → already a list
PATTERNS
list(map(lambda x: x * 2, numbers))
list(map(lambda x: [Link](), names))
list(filter(lambda x: x % 2 == 0, numbers))
list(filter(lambda x: x > 20, numbers))
sorted(words, key=lambda x: len(x))
sorted(students, key=lambda x: x["marks"], reverse=True)
# Inline if/else
lambda x: "A" if x>=80 else "B" if x>=50 else "C"
Dict unpacking — add key without changing original
list(map(
lambda x: {**x, "grade": "A" if x["marks"]>=80 else "B" if x["marks"]>=50 else
"C"},
students
))
Combine map + filter
list(map(lambda x: x**2, filter(lambda x: x%2==0, numbers)))
RULES
• Always wrap map() and filter() with list()
• x = each ITEM from the list, not the index
• Python is case-sensitive: x ≠ X
• sorted() without key= sorts alphabetically by default
• f-strings: use single quotes inside f"{i['key']}"
• {**x, "new_key": value} copies dict x and adds/overwrites key
• Lambda for short logic only — use def for anything complex
4. OOP
4 PILLARS
• Encapsulation → hide data, access via methods (self.__attr)
• Inheritance → child gets parent for free (class Child(Parent):)
• Polymorphism → same method name, different behaviour per class
• Abstraction → show interface, hide internals (ABC + @abstractmethod)
SYNTAX REFERENCE
class MyClass: → define class
def __init__(self, arg): → constructor
[Link] = value → store attribute
obj = MyClass(arg) → create object
class Child(Parent): → inherit
super().__init__(args) → call parent constructor
self.__attr → private attribute
def get_attr(self): return self.__attr → getter
def set_attr(self,v): self.__attr = v → setter
PATTERNS - Basic Class
class Dog:
def __init__(self, name, breed):
[Link] = name
[Link] = breed
def bark(self):
print(f"{[Link]} says Woof!")
SELF RULES
• self = "this specific object right now"
• Every method must have self as first parameter
• Never pass self manually — Python does it automatically
• [Link]() is secretly [Link](dog1)
• [Link] stores data permanently inside the object
SUPER() RULES
• Only needed when child has its OWN __init__ with extra attributes
• If child has no __init__, Python uses parent's automatically
• Always call super().__init__() as VERY FIRST line in child __init__
• Without super() → parent attributes never set → AttributeError
GENERAL OOP RULES
• NEVER use as variable names: type, list, id, input, max, min, sum, len, range, dict, set
• Abstraction hides HOW. Encapsulation hides DATA. Different things.
• Abstract class cannot be instantiated → TypeError (this is correct)
• Every child MUST implement all @abstractmethod methods
• Polymorphism: write once, works for all current + future objects
• Method overriding itself IS polymorphism — a loop just shows it
• self.__attr accessed outside class → AttributeError (correct behaviour)
5. EXCEPTION HANDLING
STRUCTURE
try: → code that might fail (always runs first)
except: → runs ONLY if that specific error occurred
else: → runs ONLY if NO exception occurred
finally: → ALWAYS runs last (cleanup: close files, free resources)
COMMON BUILT-IN EXCEPTIONS
ValueError → wrong value type (int('abc'))
ZeroDivisionError → division by zero (10 / 0)
FileNotFoundError → file doesn't exist (open('[Link]'))
TypeError → wrong data type ('a' + 1)
IndexError → list index out of range (lst[99])
KeyError → dict key missing (d['bad_key'])
KEY PATTERNS
Full try/except/else/finally structure:
try:
result = 10 / int(input("Enter: "))
except ValueError:
print("Not a valid number!")
except ZeroDivisionError:
print("Cannot divide by zero!")
else:
print(f"Result: {result}")
finally:
print("Done.")
Capture error message with 'as e':
try:
x = int("abc")
except Exception as e:
print("Error:", e)
Golden pattern: raise inside / catch outside:
def divide(a, b):
if b == 0:
raise ZeroDivisionError("Divider cannot be zero")
return a / b
RULES
• try/except INSIDE loop → loop continues after error
• try/except OUTSIDE loop → one error kills the entire loop
• raise exits the function immediately — no else needed after it
• Functions RAISE errors. Calling code CATCHES them. (professional pattern)
• Custom exceptions: inherit from Exception, use pass if no extra logic
• Custom name should describe the problem: InvalidAgeError, NegativeValueError
• Use 'as e' to capture and display the actual error message
• Always protect int(input()) — users will type letters eventually
• Test edge cases: empty input, zero, negative, very large numbers
• len(name) < 2 already covers name == '' — don't write both