ویژگی تصویر

آشنایی جامع با کتابخانه enum در پایتون

  /  پایتون   /  کتابخانه enum در پایتون
بنر تبلیغاتی الف

کتابخانه enum در پایتون (ماژول enum) ابزاری استاندارد و قدرتمند برای تعریف «مجموعه‌های ثابت» (enumerations) است. این ماژول از پایتون 3.4 به بعد در هسته زبان قرار دارد و برای مدل‌سازی مقادیر معنادار ثابت مثل وضعیت‌ها، انواع خطا، یا گزینه‌های پیکربندی بسیار مناسب است.

چرا از enum استفاده کنیم؟

  • خوانایی بالاتر کد: نام‌های معنایی به‌جای اعداد یا رشته‌های پراکنده.
  • کاهش خطا: مقدارهای نامعتبر راحت‌تر شناسایی می‌شوند.
  • قابلیت‌های اضافی: قابلیت مقایسه، سلسله‌مراتب انواع، و عملیات بیت‌به‌بیت در Flag.

تعریف ساده Enum

from enum import Enum, auto

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = auto()

در این مثال کلاس Color سه عضو دارد. متد auto() اجازه می‌دهد پایتون به‌صورت خودکار مقدار عددی تعیین کند. استفاده از Enum باعث می‌شود Color.RED یک عضو مشخص و یکتا باشد.

دسترسی، نام و مقدار

print(Color.RED)         # Color.RED
print(Color.RED.name)    # 'RED'
print(Color.RED.value)   # 1

با .name و .value می‌توان نام و مقدار هر عضو را گرفت. این مقادیر برای نمایش، لاگینگ و سریال‌سازی کاربردی‌اند.

IntEnum برای سازگاری با عددها

from enum import IntEnum

class Status(IntEnum):
    OK = 200
    NOT_FOUND = 404

IntEnum مانند Enum است ولی اعضا از نوع عددی (عدد صحیح) عمل می‌کنند و می‌توان آن‌ها را مستقیماً با اعداد مقایسه یا در جاهایی که عدد لازم است استفاده کرد.

Flag و عملیات بیت‌به‌بیت

from enum import Flag, auto

class Permission(Flag):
    READ = auto()
    WRITE = auto()
    EXECUTE = auto()

# ترکیب مجوزها
rw = Permission.READ | Permission.WRITE

Flag برای ترکیب بیت‌ها مناسب است؛ به‌عنوان مثال مجوزها یا پرچم‌های متعدد. می‌توان از عملگرهای |, &, ~ استفاده کرد تا ترکیب‌ها و تست‌ها را انجام داد.

تزویج unique و جلوگیری از مقادیر تکراری

from enum import unique

@unique
class Color2(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

دکوراتور @unique تضمین می‌کند مقادیر تکراری تعریف نشوند؛ اگر مقدار تکراری باشد، در زمان تعریف کلاس خطا رخ می‌دهد که برای جلوگیری از اشتباهات در مجموعه‌های ثابت مفید است.

API تابعی (Functional API)

from enum import Enum

Weekday = Enum('Weekday', 'MON TUE WED THU FRI SAT SUN')

این روش برای ایجاد سریع enumeration در زمان اجرا مناسب است، مثلاً زمانی که نام اعضا از یک منبع خارجی می‌آیند یا داینامیک ساخته می‌شوند.

تبدیل از مقدار به عضو Enum

print(Color(1))        # Color.RED
# در IntEnum می‌توان
print(Status(200) == Status.OK)  # True

می‌توان از مقدار عددی یک Enum عضو متناظر را ساخت. اگر مقدار نامعتبر باشد، خطای ValueError ایجاد می‌شود.

مثالی کامل‌تر: استفاده در پروژه

from enum import Enum, auto

class OrderState(Enum):
    NEW = auto()
    PROCESSING = auto()
    SHIPPED = auto()
    DELIVERED = auto()
    CANCELLED = auto()

def can_cancel(state: OrderState) -> bool:
    return state in {OrderState.NEW, OrderState.PROCESSING}

در این مثال تابع can_cancel با استفاده از Enum وضعیت سفارش را مدیریت می‌کند. این سبک کدنویسی خطاهای منطقی را کاهش می‌دهد و خوانایی را افزایش می‌دهد.

سریال‌سازی و JSON

import json
from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2

data = {'color': Color.RED}
# json.dumps(data) خطا می‌دهد

در حالت عادی json.dumps نمی‌تواند یک عضو Enum را سریال کند؛ باید یا مقدار یا نام را ارسال کنیم، یا یک JSONEncoder سفارشی بنویسیم:

class EnumEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Enum):
            return obj.name
        return json.JSONEncoder.default(self, obj)

json.dumps(data, cls=EnumEncoder)  # '{"color": "RED"}'

در این نمونه، اعضای Enum با نامشان سریال می‌شوند؛ می‌توان به‌جای نام از .value نیز استفاده کرد.

جدول مقایسه انواع Enum

نوعکاربردویژگی‌های کلیدی
Enumمجموعه‌های ثابت عمومیعضوهای یکتا، نام و مقدار
IntEnumاعضا با رفتار عددیقابل مقایسه با اعداد صحیح
Flagپرچم‌ها/مجوزهاعملیات بیت‌به‌بیت، ترکیب‌بندی

نکات پیشرفته و بهترین شیوه‌ها

  • از @unique برای جلوگیری از اشتباهات تعریف استفاده کنید.
  • اگر برای API یا دیتابیس سریال‌سازی می‌کنید، تصمیم واضحی برای استفاده از نام یا مقدار بگیرید و مستندسازی کنید.
  • برای مقایسه با اعداد از IntEnum استفاده کنید؛ وگرنه مقایسه مستقیم با عدد ممکن است منجر به خطا شود.
  • برای حالت‌هایی که نیاز به رفتار دلخواه اعضا دارید، متدها و پراپرتی‌ها را داخل کلاس Enum پیاده‌سازی کنید.

خطاهای رایج و رفع آن‌ها

# اشتباه رایج: تلاش برای تغییر مقدار عضو
Color.RED = 10  # خطا یا بی‌اثر است؛ Enumها نا‌قابل‌تغییر در نظر گرفته می‌شوند

اعضا در Enum نباید تغییر کنند؛ اگر نیاز به نگه‌داشتن متادیتا دارید، از پراپرتی یا نگهداری متناظر نام/مقدار در ساختار دیگر استفاده کنید.

جمع‌بندی

ماژول enum کتابخانه‌ای استاندارد و ضروری برای مدل‌سازی مقادیر ثابت در پایتون است. انتخاب بین Enum، IntEnum و Flag بسته به نیازهای پروژه متفاوت است. استفاده از این الگوها باعث خواناتر شدن کد، کاهش خطا و قابلیت نگهداری بهتر می‌شود.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: