Encapsulation and Method Types
Now you'll master professional-grade class design through access control and multiple method types. In this lesson, you'll build a Task class with factory methods and utility functions, learn from AI how to protect attributes and design methods, challenge AI with real-world design decisions across multiple domains, and build a comprehensive guide for method selection that you'll use throughout Part 5.
Part 1: Experience Access Control and Method Types
Your Role: Code explorer discovering why data protection and method organization matter
Discovery Exercise: The Unprotected Task Problem
Create method_discovery.py:
Loading Python environment...
Output:
999
Your task 1: Identify the problems:
- What prevents setting invalid priorities (should be 1-10)?
- If I have 100 methods using
self.priority, and I need to add validation, where do I modify code?
Discovering the Solution: Method Types
Stage 2: Using Instance Methods
Loading Python environment...
Output:
5
Your task 2: Run this and observe:
- How does using methods instead of direct attribute access help?
- What happens if someone ignores the _ convention?
Stage 3: Discovering Private Attributes
Loading Python environment...
Output:
1
Your task 3: Run this and answer:
- Can you access __priority directly?
- Is this truly "private" or just annoying?
Discovery Exercise 2: Three Method Types with Task Class

Stage 4: Instance Methods vs Class Methods vs Static Methods (Task Focus)
Loading Python environment...
Output:
Task 'Review pull request' completed!
Created: Write tests
Urgent task priority: 1
True
False
Valid levels: {1: 'Critical', 2: 'High', 3: 'Medium-High', 5: 'Normal', 8: 'Low', 10: 'Someday'}
Total tasks created: 3
Your task 4: Run this and observe:
- Which methods need an object (instance) to work?
- Which can work with just the class (no instance)?
- Which are just utility functions grouped with the class for organization?
Your Discoveries
Document in method_type_analysis.md:
- Why do instance methods use
self? - When would you use a class method (like
create_from_dict) instead? - When would a static method (like
is_valid_priority) be useful? - Why protect attributes with methods instead of direct access?
Part 2: Learn Access Control and Method Design
Your Role: Student receiving instruction from AI Teacher
AI Teaching Prompt
Ask your AI companion:
"I've built a Task class with three method types (@classmethod for create_from_dict, @staticmethod for is_valid_priority, instance methods for mark_complete). Show me and explain:
- What's the difference between @classmethod and @staticmethod?
- When should I use each for a Task class?
- For a Task class, which method type would you use for:
- mark_complete() which changes THIS task's done status
- create_from_dict(data) which should create a new Task from a dictionary
- is_valid_priority(num) which just validates a number
- Show me how to enforce that priority can only be 1-10 using a property."
Convergence Activity
After AI explains, ask: "Show me how the @property decorator works for protecting priority while allowing read access. Why is this better than a get_priority() method? Can I use this with create_from_dict()?"
Deliverable: Write summary explaining when to use each method type in the context of a Task class, with examples of when you'd use each.
Part 3: Challenge AI with Method Design
Your Role: Student teaching AI by testing design understanding
Challenge 1: Task Factory Patterns
"Show me a Task class where you have TWO class methods: create_from_dict() for creating from a dictionary, and create_urgent() as a shortcut for high-priority tasks. Why are these class methods instead of instance methods or static methods? When would each be called during development?"
Challenge 2: Properties vs Methods
"In a Task class with a
_priorityattribute, would you expose it as:
- A method: task.get_priority()
- A property: task.priority (looks like attribute but uses @property)
Which feels more Pythonic? Why? Show me both versions and explain the tradeoffs."
Challenge 3: Static Methods in Practice
"When would a static method be useful in a Task class? Show me two examples: one for validation (is_valid_priority) and one for data lookup (priority_levels). What about for other domains like Case, Invoice, or Appointment management? When would you use static methods vs module-level functions?"
Deliverable
Document challenges and AI responses with your analysis across multiple domains.
Part 4: Reusable Patterns Across Domains
Your Role: Knowledge synthesizer creating design framework
You've mastered method types with Task. Now apply the same patterns across different domains:
Task Pattern (Primary Example)
Loading Python environment...
Auxiliary Domain 1: Legal (Case Management)
Loading Python environment...
Auxiliary Domain 2: Finance (Invoice Management)
Loading Python environment...
Method Types and Encapsulation Guide
Create method_types_and_encapsulation_guide.md:
Instance Methods - Use when: Method operates on specific object's data
Loading Python environment...
Class Methods (@classmethod) - Use when: Creating instances (factories) or class-level operations
Loading Python environment...
Static Methods (@staticmethod) - Use when: Utility function grouped with class but doesn't need instance or class
Loading Python environment...
Access Levels:
- Public:
self.name- Direct access encouraged - Protected:
self._priority- Convention, don't access directly - Private:
self.__internal- Name mangled, strongly discourage access
Properties (@property/@setter) - Make attributes look like data while using method validation
Loading Python environment...
Deliverable: Complete guide with method type selection criteria and patterns from Task, Case, Invoice domains.
Try With AI
Ready to master encapsulation, method types, and properties using the Task class as your anchor?
Explore Access Control Levels:
"Build a Task class with three attributes: title (public), _priority (protected, convention), __completion_code (private, name-mangled). Show me how to access each from outside the class. Explain why priority should be protected and what Python's name mangling does with __completion_code. Then show the same pattern for a Case class in a legal domain."
What you're learning: The three access control levels give you flexibility. Public attributes are fast and simple. Protected attributes signal "don't touch this from outside" by convention. Private attributes use Python's name mangling to make accidental access harder. This same strategy applies to any class in any domain.
Master Task Class Methods and Static Methods:
"Create a Task class with: 1) create_from_dict() class method for building from dictionaries, 2) create_urgent() class method as a factory for high-priority tasks, 3) is_valid_priority() static method to validate numbers, 4) priority_levels() static method to return the lookup table. Show me how each works. Why can't instance methods do what class methods do? Why are static methods better than just module-level functions?"
What you're learning: Class methods are factories that create instances without needing one first. Static methods are utilities grouped with the class. You'll use this exact pattern in Part 5: Task.create_from_dict(), Case.create_from_database(), Invoice.create_from_json(). The pattern is universal.
Test Properties for Validation:
"Build a Task class with priority property. Use @property for getter, @priority.setter for setter that validates (1 to 10 range). Try: task.priority = -5, task.priority = 200, task.priority = 5. Show how properties enable validation without breaking the attribute access API. Why is this better than get_priority()/set_priority() methods? Show this same pattern for an Invoice class with amount validation (must be positive)."
What you're learning: Properties look like attributes from the outside but use methods internally. This is Pythonic—clean API, hidden validation. The pattern transfers across domains: validate Task priority, Invoice amount, Appointment time, Case status.
Apply Class Methods Across Domains:
"I'm building systems for Task management, legal cases, and invoices. Show me how each would use @classmethod as a factory: Task.create_from_dict(), Case.create_from_database(), Invoice.create_from_json(). Why does each use a class method instead of just calling init? When would you need to do extra setup before returning the instance?"
What you're learning: Class methods are the pattern for constructing objects with complex setup. Task might need to generate IDs, Case might need to deserialize nested objects, Invoice might need to calculate totals. The pattern works everywhere once you understand why class methods have access to the class itself.