Advanced Functions and OOP¶
By the end of this lesson you'll be able to:
- Use
map(),filter(),any(),all(),chr(),ord(),dir(), andhelp()effectively - Create custom exception classes and use exception chaining
- Define properties with
@propertyand use dunder methods to customize object behavior - Apply object composition to build complex objects from simpler ones
This chapter fills in the remaining advanced tools from Python's functional and OOP toolkit.
Welcome to Chapter 31!
This is where your Python skills reach professional level!
Custom exceptions, properties, dunder methods — these are the tools that separate beginner code from expert code.
Let's level up! Let's code it together!
map() and filter() with Named Functions¶
You saw map() and filter() with lambdas in Chapter 22. They work just as well with named functions:
1 2 3 4 5 6 7 8 9 | |
This style is more readable than lambdas for complex logic.
any() and all()¶
any(iterable) returns True if at least one item is truthy.
all(iterable) returns True if every item is truthy.
Both short-circuit — they stop as soon as the answer is known.
chr() and ord() — Characters and ASCII Codes¶
ord(character) converts a character to its ASCII (Unicode) integer code.
chr(integer) does the reverse — converts an integer to its character.
1 2 3 4 | |
dir() and help() — Exploring Objects¶
dir(obj) returns a list of all attributes and methods available on obj.
help(obj) prints detailed documentation.
These are your best friends when exploring an unfamiliar module or object:
1 2 3 | |
id() and hash()¶
id(obj) returns the unique memory address of an object.
Two variables with the same id are the same object — not just equal, but literally the same in memory.
hash(obj) returns a hash value (an integer fingerprint). Dictionaries use hashes for fast lookups.
Only immutable objects (strings, numbers, tuples) can be hashed.
What Do You Think Will Happen?
The code below compares is vs == for strings. Will the small strings share the same id?
Make your guess — then run it!
Custom Exception Classes¶
You can create your own exception types by subclassing Exception.
Custom exceptions make your error messages much clearer to users of your code.
1 2 3 4 5 6 7 | |
Static Methods¶
A static method belongs to the class but doesn't need access to self (the instance).
Decorate it with @staticmethod. Use it for utility functions that logically belong to the class.
1 2 3 4 5 6 7 8 9 10 | |
Properties with @property¶
A property lets you define a method that behaves like an attribute. This lets you add validation or computation to attribute access without changing the interface.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
Dunder Methods Overview¶
Dunder methods (also called "magic methods") are special methods with double underscores on both sides.
You've already seen __init__ and __str__. There are many more:
| Method | Called when |
|---|---|
__len__(self) |
len(obj) |
__add__(self, other) |
obj + other |
__eq__(self, other) |
obj == other |
__lt__(self, other) |
obj < other |
__contains__(self, item) |
item in obj |
__iter__(self) |
for x in obj |
__getitem__(self, key) |
obj[key] |
By implementing dunders, your custom classes work naturally with Python operators and built-in functions.
Object Composition¶
Object composition means building a complex object from simpler objects — storing instances of one class inside another.
This is often better than deep inheritance hierarchies:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Composition over Inheritance
Professional Python developers prefer composition over deep inheritance.
Instead of ElectricCar(Car(Vehicle)), build ElectricCar with an engine attribute.
It's easier to change individual parts without breaking unrelated code.
Learning Check¶
Your Turn — Add a Dunder Method
The Bag class below stores items, but len(bag) doesn't work yet.
Add the __len__ dunder method so len(bag) returns the number of items!
Experiments¶
Try these changes. Predict what will happen first, then run it to check!
-
Use
any()to check if any string in a list has more than 10 characters. You'll know it worked when the result isTrueorFalsebased on the actual lengths. -
Write a Caesar cipher decryption function (shift by -3 instead of +3). Encrypt then decrypt "Hello". You'll know it worked when you get back the original "Hello".
-
Add
__add__to theBagclass sobag1 + bag2returns a new Bag with all items from both. You'll know it worked whenlen(bag1 + bag2)equalslen(bag1) + len(bag2). -
Add
@property areato aRectangleclass. Ensure it recomputes every time width or height changes. You'll know it worked when changingr.width = 10updatesr.areaautomatically. -
Create a
Stackclass using composition (it has alistattribute) withpush,pop,peek, and__len__. You'll know it worked when all four operations work as expected.
Python Expert!
You've reached the advanced Python tier! Custom exceptions, properties, dunders, and composition are tools used by professional Python developers every day.
The last chapters take you into data science and machine learning territory. Let's keep coding!