מדריך זה מכסה תכנות מונחה עצמים (OOP) ב-Python ומנהלי הקשר (Context Managers), כולל דוגמאות מעשיות ל-לכידת stdout/stderr ושימוש בתבנית Tee להצגת פלט ולכידתו בו-זמנית.
In Questo Articolo
1. מחלקות ב-Python
מחלקות הן מנגנון מרכזי ב-OOP. מחלקה היא תבנית ליצירת אובייקטים עם תכונות (נתונים) ו-שיטות (פונקציות). אובייקטים שנוצרים ממחלקה נקראים מופעים (instances). מחלקות מאפשרות לארגן את הקוד, לשפר את השימוש החוזר ולהקל על תחזוקה.
מבנה מחלקה
class ClassName:
def __init__(self, param1, param2):
self.param1 = param1
self.param2 = param2
def method(self):
return f'{self.param1} ו-{self.param2}'
נקודות מפתח:
__init__: בונה לאתחול תכונות האובייקט.self: מתייחס למופע הנוכחי.- תכונות: מוגדרות דרך
selfוזמינות בכל השיטות. - שיטות: עובדות עם נתוני האובייקט.
יצירת אובייקטים
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def description(self):
return f'{self.year} {self.make} {self.model}'
my_car = Car('Toyota', 'Corolla', 2020)
print(my_car.description()) # פלט: 2020 Toyota Corolla
סוגי שיטות
- שיטות מופע — עובדות על האובייקט (
self). - שיטות מחלקה — עובדות על המחלקה (
cls) בעזרת@classmethod. - שיטות סטטיות — בלתי תלויות במופע או במחלקה (
@staticmethod).
ירושה
class Animal:
def speak(self):
return 'קול של חיה'
class Dog(Animal):
def speak(self):
return 'נביחה'
פולימורפיזם
class Cat(Animal):
def speak(self):
return 'מיאו'
cat = Cat()
print(cat.speak()) # פלט: מיאו
- אותו שם של שיטה יכול לפעול אחרת בהתאם לסוג האובייקט.
אנקפסולציה
class Car:
def __init__(self, make, model):
self._make = make # תכונה מוגנת
self._model = model
def get_make(self):
return self._make
def set_make(self, make):
self._make = make
שיטות קסם והרסן
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'Point({self.x}, {self.y})'
p = Point(3, 4)
print(p) # פלט: Point(3, 4)
דיאגרמת ASCII: ירושה ופולימורפיזם
┌─────────┐
│ Animal │
└─────────┘
│ speak() │
└─────────┘
▲
┌───────┴────────┐
│ │
┌─────────┐ ┌─────────┐
│ Dog │ │ Cat │
└─────────┘ └─────────┘
│ speak() │ │ speak() │
└─────────┘ └─────────┘
2. מנהלי הקשר ב-Python
מנהלי הקשר מאפשרים הקצאה ושחרור משאבים אוטומטית, גם במקרה של שגיאות.
שימוש ב-@contextmanager
from contextlib import contextmanager
@contextmanager
def my_context():
print("כניסה להקשר")
try:
yield "משאב"
finally:
print("יציאה מהקשר")
שימוש:
with my_context() as res:
print("בתוך ההקשר:", res)
לכידת stdout/stderr ו-Tee
Python מאפשר לכידת stdout, stderr או שניהם, וכן הצגה ולכידה בו-זמנית עם תבנית Tee.
3. דוגמה מלאה: oop_and_context.py
"""
oop_and_context.py
דוגמאות למחלקות, עקרונות OOP ומנהלי הקשר ב-Python.
כולל:
- הגדרת מחלקות, ירושה, פולימורפיזם ואנקפסולציה
- שיטות מופע, מחלקה וסטטיות
- שיטות קסם והרסן
- מנהלי הקשר עם @contextmanager
- לכידת stdout, stderr ושניהם יחד
- תבנית Tee: הצגה ולכידה בו-זמנית
- מנהל הקשר מבוסס מחלקה
"""
import sys
import io
from contextlib import contextmanager
# ==========================
# חלק 1: מחלקות ו-OOP
# ==========================
class Animal:
"""מחלקת בסיס לחיות"""
def speak(self):
return 'קול של חיה'
class Dog(Animal):
def speak(self):
return 'נביחה'
class Cat(Animal):
def speak(self):
return 'מיאו'
class Car:
"""דוגמה לאנקפסולציה"""
def __init__(self, make, model, year=None):
self._make = make
self._model = model
self.year = year
def get_make(self):
return self._make
def set_make(self, make):
self._make = make
def description(self):
if self.year:
return f'{self.year} {self._make} {self._model}'
return f'{self._make} {self._model}'
class Point:
"""מחלקה עם שיטות קסם"""
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'Point({self.x}, {self.y})'
# ==========================
# חלק 2: מנהלי הקשר
# ==========================
@contextmanager
def my_context():
print("כניסה להקשר")
try:
yield "משאב"
finally:
print("יציאה מהקשר")
@contextmanager
def capture_stdout():
old_stdout = sys.stdout
sys.stdout = buffer = io.StringIO()
try:
yield buffer
finally:
sys.stdout = old_stdout
@contextmanager
def capture_stderr():
old_stderr = sys.stderr
sys.stderr = buffer = io.StringIO()
try:
yield buffer
finally:
sys.stderr = old_stderr
@contextmanager
def capture_output():
old_stdout = sys.stdout
old_stderr = sys.stderr
sys.stdout = sys.stderr = buffer = io.StringIO()
try:
yield buffer
finally:
sys.stdout = old_stdout
sys.stderr = old_stderr
class Tee(io.StringIO):
"""הצגה ולכידה בו-זמנית"""
def __init__(self, original):
super().__init__()
self.original = original
def write(self, text):
self.original.write(text)
super().write(text)
def flush(self):
self.original.flush()
@contextmanager
def capture_stdout_tee():
old_stdout = sys.stdout
sys.stdout = tee = Tee(old_stdout)
try:
yield tee
finally:
sys.stdout = old_stdout
# ==========================
# חלק 3: מנהל הקשר מבוסס מחלקה
# ==========================
class OutputCapture:
"""מנהל הקשר מבוסס מחלקה ללכידת stdout"""
def __init__(self):
self._buffer = io.StringIO()
self._old_stdout = None
def __enter__(self):
self._old_stdout = sys.stdout
sys.stdout = self._buffer
return self._buffer
def __exit__(self, exc_type, exc_val, exc_tb):
sys.stdout = self._old_stdout
return False # להעביר את החריגות
# ==========================
# חלק 4: הדגמות
# ==========================
def demo_classes():
print("\n--- הדגמת מחלקות ---")
dog = Dog()
cat = Cat()
print("כלב אומר:", dog.speak())
print("חתול אומר:", cat.speak())
my_car = Car('Toyota', 'Corolla', 2020)
print("תיאור הרכב:", my_car.description())
my_car.set_make('Honda')
print("מותג מעודכן:", my_car.get_make())
point = Point(3, 4)
print("נקודה:", point)
def demo_context_managers():
print("\n--- הדגמת מנהלי הקשר ---")
with my_context() as res:
print("בתוך ההקשר:",res)