سطح مقدماتی (Beginner Level)
یکی از قدرتهای اصلی پایتون، پویایی (Dynamic) بودن آن است. برخلاف بسیاری از زبانهای برنامهنویسی که نام متغیرها و متدها باید در زمان کدنویسی مشخص باشند، در پایتون میتوانید با استفاده از رشتهها (Strings) به ویژگیهای (Attributes) یک شیء دسترسی داشته باشید یا آنها را تغییر دهید.
پایتون ۴ تابع داخلی (Built-in) برای این کار ارائه میدهد:
hasattr(object, name): بررسی میکند آیا ویژگی وجود دارد یا خیر.getattr(object, name[, default]): مقدار ویژگی را برمیگرداند.setattr(object, name, value): مقدار ویژگی را تنظیم میکند (یا ویژگی جدید میسازد).delattr(object, name): ویژگی را حذف میکند.
۱. بررسی و دریافت مقدار (hasattr و getattr)
زمانی که مطمئن نیستید یک شیء دارای ویژگی خاصی است، استفاده مستقیم از . (مثل obj.x) ممکن است باعث خطای AttributeError شود. توابع hasattr و getattr راه ایمنتری هستند.
سینتکس:
hasattr(obj, "score")-> مقدارTrueیاFalseبرمیگرداند.getattr(obj, "score", 0)-> اگرscoreوجود داشته باشد مقدارش را میدهد، وگرنه مقدار پیشفرض0را برمیگرداند.
# مثال ۲: کاربرد در توابع (Static Snippet)
def get_info(obj, attribute_name):
# اگر ویژگی وجود نداشت، None برگردان
return getattr(obj, attribute_name, None)
۲. تنظیم و حذف مقدار (setattr و delattr)
با setattr میتوانید مقادیر را تغییر دهید یا حتی ویژگیهای جدیدی به شیء اضافه کنید که در کلاس تعریف نشدهاند (البته اگر کلاس محدود نشده باشد).
# مثال ۴: کپی کردن اطلاعات از دیکشنری به شیء (Static Snippet)
def dict_to_obj(obj, data_dict):
for key, value in data_dict.items():
setattr(obj, key, value)
سطح پیشرفته (Professional Level)
در سطح حرفهای، این توابع جایگزین بسیار امنتری برای eval() هستند و اساس کار بسیاری از فریمورکها (مثل ORMها در Django یا SQLAlchemy) را تشکیل میدهند.
۱. فراخوانی متدها با نام (Dynamic Dispatch)
از آنجا که متدها در پایتون نیز "ویژگی" محسوب میشوند، میتوانید با getattr یک متد را بر اساس نامش دریافت کرده و سپس اجرا کنید. این الگو برای ساخت سیستمهای پلاگین (Plugin Systems) یا Command Pattern بسیار کاربردی است.
۲. نکات امنیتی و Performance
استفاده از getattr کمی کندتر از دسترسی مستقیم با نقطه (.) است، اما در اکثر برنامهها این افت سرعت ناچیز است. با این حال، بزرگترین نکته بحث امنیت است.
هرگز اجازه ندهید کاربران مستقیماً هر ویژگیای را صدا بزنند. به مثال زیر توجه کنید که چگونه میتوان دسترسی را محدود کرد.
۳. تفاوت با Magic Methodها
باید دقت کنید که getattr(obj, 'name') تابعی است که از بیرون صدا زده میشود. اما متد جادویی __getattr__ درون کلاس تعریف میشود و فقط زمانی اجرا میشود که ویژگی پیدا نشود.
ترکیب getattr (تابع داخلی) با __getattr__ (متد کلاس) الگوی قدرتمندی برای مدیریت تنظیمات (Configuration) یا پروکسیها (Proxies) است.
# مثال پیشرفته ۳: الگوی Proxy (Static Snippet)
class Wrapper:
def __init__(self, wrapped):
self._wrapped = wrapped
def __getattr__(self, name):
# درخواستها را به شیء داخلی پاس میدهد
print(f"Accessing {name} via Wrapper")
return getattr(self._wrapped, name)