در بسیاری از زبانهای برنامهنویسی مانند C++ یا Java، کلمات کلیدی مشخصی (مانند const یا final) وجود دارد که از تغییر مقدار یک متغیر جلوگیری میکند. اما پایتون رویکرد متفاوتی دارد. در پایتون، "ثابتها" (Constants) به صورت پیشفرض وجود ندارند، اما ما با استفاده از قراردادهای نامگذاری و تکنیکهای پیشرفته، رفتار آنها را شبیهسازی میکنیم.
در این مقاله، از سطح مقدماتی تا تکنیکهای بسیار پیشرفته برای مدیریت مقادیر ثابت را بررسی خواهیم کرد.
سطح مقدماتی (Beginner Level)
در این سطح با مفهوم پایه ثابتها و نحوه تعریف آنها طبق استانداردهای کامیونیتی پایتون (PEP 8) آشنا میشویم.
مفهوم ثابتها و قرارداد نامگذاری
یک ثابت (Constant) متغیری است که مقدار آن در طول اجرای برنامه نباید تغییر کند. مثالهایی از ثابتها شامل عدد پی (PI)، آدرس دیتابیس، یا حداکثر تعداد تلاش برای ورود کاربر است.
در پایتون، برای نشان دادن اینکه یک متغیر "ثابت" است، نام آن را با حروف بزرگ انگلیسی (UPPER_CASE) مینویسیم. اگر نام شامل چند کلمه باشد، آنها را با _ جدا میکنیم.
نکته مهم: این فقط یک قرارداد است. مفسر پایتون مانع تغییر این مقادیر نمیشود، اما برنامهنویسان دیگر با دیدن حروف بزرگ میفهمند که نباید این مقدار را تغییر دهند.
مثال ۱: تعریف ثابتهای ساده (Static Code)
این قطعه کد صرفاً نحوه تعریف را نشان میدهد و به تنهایی خروجی ندارد، بنابراین از بلوک استاتیک استفاده میکنیم.
# تعریف ثابتها با حروف بزرگ
PI = 3.14159
MAX_USER_CONNECTIONS = 100
DEFAULT_TIMEOUT = 30
# این یک متغیر معمولی است (نه ثابت)
user_age = 25
مثال ۲: استفاده عملیاتی از ثابتها (Interactive Code)
در اینجا یک اسکریپت کامل داریم که مساحت دایره را با استفاده از یک ثابت محاسبه میکند.
چرا باید از ثابتها استفاده کنیم؟
استفاده از مقادیر عددی یا رشتهای به صورت مستقیم (Hard-coding) در کد، باعث کاهش خوانایی و سخت شدن نگهداری کد میشود.
- خوانایی:
MAX_RETRYبسیار گویاتر از عدد5در وسط کد است. - نگهداری: اگر بخواهید عدد را عوض کنید، فقط کافیست یک جا (تعریف ثابت) را تغییر دهید.
مثال ۳: فیزیک و گرانش (Interactive Code)
محاسبه وزن اجسام با استفاده از ثابت گرانش زمین.
سطح پیشرفته (Professional Level)
در سطح حرفهای، تکیه بر "قراردادهای اخلاقی" کافی نیست. ما نیاز به ابزارهایی داریم که تغییر ناپذیری را تضمین کنند یا حداقل به ابزارهای تحلیل کد (Linters) کمک کنند تا خطاها را پیدا کنند.
۱. استفاده از typing.Final (پایتون ۳.۸ و بالاتر)
ماژول typing ابزاری به نام Final ارائه میدهد. این ابزار در زمان اجرا (Runtime) جلوی تغییر را نمیگیرد، اما ابزارهای بررسی کد (مانند Mypy) و IDEهای پیشرفته (مانند VS Code و PyCharm) در صورت تلاش برای تغییر مقدار، به شما خطا نشان میدهند.
مثال ۱: استفاده از Type Hint برای ثابتها
در این مثال کد اجرا میشود (چون پایتون داینامیک است)، اما یک IDE استاندارد روی خط آخر خطای تایپی نشان میدهد.
۲. استفاده از Enum برای گروهبندی ثابتها
زمانی که مجموعهای از ثابتهای مرتبط دارید، بهترین روش استفاده از کلاس Enum است. این روش خوانایی را به شدت بالا میبرد و از تغییر مقادیر جلوگیری میکند.
مثال ۲: وضعیتهای کاربر با Enum
در اینجا اگر بخواهید مقدار یک عضو Enum را تغییر دهید، پایتون خطای AttributeError میدهد.
۳. ایجاد کلاسهای تغییرناپذیر (Custom Frozen Class)
برای کنترل کامل، میتوانیم کلاسی بسازیم که متد __setattr__ را بازنویسی (Override) کند تا جلوی تغییر مقدار ویژگیها را بگیرد. این روش برای ساخت فایلهای تنظیمات (config) بسیار کاربردی است.
مثال ۳: کلاس تنظیمات قفل شده (Strictly Immutable)
این کد نشان میدهد چگونه میتوان مکانیزمی ساخت که در صورت تلاش برای تغییر مقدار، برنامه با خطا متوقف شود.
۴. استفاده از Dataclasses با frozen=True
یک روش مدرنتر و پایتونیک برای داشتن اشیایی که مقادیرشان ثابت است، استفاده از dataclasses است.
# Static Snippet: Frozen Dataclass Definition
from dataclasses import dataclass
@dataclass(frozen=True)
class AppConfig:
host: str
port: int
db_name: str
# config = AppConfig("localhost", 8080, "users")
# config.port = 9090 # This raises FrozenInstanceError
مدیریت فایلهای ثابت (Best Practices)
در پروژههای بزرگ، هرگز ثابتها را در فایلهای اصلی کد پخش نکنید. بهترین روش ایجاد یک فایل جداگانه است:
- یک فایل به نام
constants.pyیاconfig.pyبسازید. - تمام ثابتها را آنجا تعریف کنید.
- آنها را در فایلهای دیگر
importکنید.
# ساختار پیشنهادی پروژه (Static)
# src/
# ├── main.py
# ├── constants.py
# └── utils.py
جمعبندی نکات حرفهای
- برای مقادیر ساده از UPPER_CASE استفاده کنید.
- برای گروههای مرتبط (مثل وضعیتها، رنگها) از Enum استفاده کنید.
- برای تنظیمات برنامه که نباید تغییر کنند، از dataclasses(frozen=True) یا typing.Final استفاده کنید.