بازتاب (reflection) یعنی «برنامهای که خودش را میخواند»: در زمان اجرا بپرسی این شیء چیست، چه ویژگیهایی دارد و چه متدهایی میفهمد. در پایتون این کار روزمره است، نه جادوی پیشرفته.
جعبهابزار دروننگری
class Book:
"""کتاب سادهٔ کتابخانه."""
def __init__(self, title):
self.title = title
def describe(self):
return f"کتاب: {self.title}"
b = Book("شازده کوچولو")
print(type(b)) # <class 'Book'>
print(isinstance(b, Book)) # True
print(hasattr(b, "title")) # True
print(getattr(b, "title")) # شازده کوچولو
print([m for m in dir(b) if not m.startswith("_")])
برای کاوش عمیقتر ماژول inspect است: inspect.signature امضای تابع را میدهد و inspect.getsource (وقتی سورس در دسترس باشد) کدش را. اعلانهای نوع هم با __annotations__ در زمان اجرا خواندنیاند — یعنی نوعها فقط برای mypy نیستند، فرادادهٔ اجراییاند.
بستار: تابعی که محیطش را یادش میماند
def make_counter():
count = 0
def inc():
nonlocal count
count += 1
return count
return inc
c = make_counter()
print(c()) # 1
print(c()) # 2 — count بین فراخوانیها زنده ماند
بستار همان کاری را میکند که در جاوا «کلاس داخلی ناشناس» میکرد، ولی با یک تابع ساده. هر جا وسوسه شدی کلاسِ تکمتده بسازی، اول بپرس: «یک بستار کافی نیست؟»
تزئینکننده: توسعهٔ رفتار بدون دستبردن در تابع
import functools, time
def timed(func):
@functools.wraps(func) # نام و مستند تابع اصلی حفظ شود
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
print(f"{func.__name__} در {time.perf_counter()-start:.4f} ثانیه")
return result
return wrapper
@timed
def slow_search(n):
return sum(range(n))
enum: انتخابهای نامدار
from enum import Enum, auto
class OrderStatus(Enum):
PENDING = auto()
PAID = auto()
SHIPPED = auto()
CANCELLED = auto()
def advance(status):
if status is OrderStatus.PAID:
return OrderStatus.SHIPPED
return status
رشتههای پراکنده («paid»، «Paid»، «PAID») منبع باگاند؛ enum انتخابها را یکی و قابل بررسی میکند.
سنجش فهم — بازتاب
۰ از ۲ پاسخ داده شده