9.2 פונקציות ומחלקות פתרון
ניקוי קוד - פונקציות¶
הבעיות שנמצאו:
- 10 פרמטרים לפונקציה - חורג בהרבה מהכלל של עד 3 פרמטרים.
- הפונקציה עושה שלושה דברים: מחשבת, מדפיסה, שולחת אימייל, ושומרת ל-DB.
- תופעת לוואי: שליחת אימייל ושמירה ל-DB בתוך פונקציה שנקראת handle_order.
- ערכים קסומים: import smtplib בתוך פונקציה.
פתרון:
from dataclasses import dataclass
@dataclass
class Customer:
name: str
email: str
@dataclass
class Product:
id: str
name: str
price_per_unit: float
@dataclass
class ShippingAddress:
address: str
city: str
country: str
def handle_order(customer: Customer, product: Product, quantity: int,
discount_percent: float, shipping: ShippingAddress) -> None:
total = calculate_total(product.price_per_unit, quantity, discount_percent)
print_order_summary(customer, product, quantity, discount_percent, total)
send_confirmation(customer.email)
save_order(customer.email, product.id, quantity)
def calculate_total(price: float, quantity: int, discount_percent: float) -> float:
total = price * quantity
return total - (total * discount_percent / 100)
def print_order_summary(customer: Customer, product: Product,
quantity: int, discount_percent: float, total: float) -> None:
print(f"Order for {customer.name}")
print(f"Email: {customer.email}")
print(f"Product: {product.name} x{quantity}")
if discount_percent > 0:
print(f"Discount: {discount_percent}%")
print(f"Total: {total}")
def send_confirmation(email: str) -> None:
print(f"Confirmation sent to {email}")
def save_order(email: str, product_id: str, quantity: int) -> None:
print("Order saved to database")
ניקוי קוד - רמות אבסטרקציה¶
def generate_report(data: list) -> None:
valid = filter_valid_entries(data)
avg = calculate_average(valid)
print_report(valid, avg)
def filter_valid_entries(data: list) -> list:
return [item for item in data if isinstance(item, dict)
and "score" in item and item["score"] >= 0]
def calculate_average(entries: list) -> float:
if not entries:
return 0
return sum(item["score"] for item in entries) / len(entries)
def print_report(entries: list, avg: float) -> None:
print("=" * 40)
print("REPORT")
print("=" * 40)
print(f"Total entries: {len(entries)}")
print(f"Average score: {avg:.2f}")
print_top_entries(entries)
def print_top_entries(entries: list) -> None:
top = sorted(entries, key=lambda x: x["score"], reverse=True)[:3]
for i, entry in enumerate(top, 1):
print(f"{i}. {entry.get('name', 'Unknown')} - {entry['score']}")
בונוס - ערכים קסומים¶
MAX_HEAVY_WEIGHT_KG = 30
HEAVY_RATE_PER_KG = 4.5
LIGHT_RATE_PER_KG = 2.8
LONG_DISTANCE_KM = 500
LONG_DISTANCE_SURCHARGE = 1.35
MIN_SHIPPING_COST = 15
def calculate_shipping(weight: float, distance: float) -> float:
if weight > MAX_HEAVY_WEIGHT_KG:
base = weight * HEAVY_RATE_PER_KG
else:
base = weight * LIGHT_RATE_PER_KG
if distance > LONG_DISTANCE_KM:
base *= LONG_DISTANCE_SURCHARGE
if base < MIN_SHIPPING_COST:
base = MIN_SHIPPING_COST
return round(base, 2)