۱۰ آبان ۱۴۰۵ florianwilhelm.info ۳ دقیقه مطالعه

نگاهی به مسئله‌ی مقدار None و استفاده از Sentinel Values در پایتون

نگاهی به مسئله‌ی مقدار None و استفاده از Sentinel Values در پایتون — Much Ado About None: Sentinel Values in Python

خلاصه

مقدار None در پایتون اغلب برای مقاصد مختلفی مانند نبود مقدار، خطا یا مقدار پیش‌فرض استفاده می‌شود که باعث ابهام در کد می‌شود. این مقاله بررسی می‌کند که چگونه مقادیر Sentinel و امکانات جدید پایتون این مشکل را در کدهای مدرن حل می‌کنند.

در زبان برنامه‌نویسی Python، مقدار None به عنوان یک ابزار همه‌کاره برای مقاصد مختلفی استفاده می‌شود. ما از آن برای نشان دادن مقادیر گم‌شده، تنظیم‌نشده، بروز خطا یا حتی به عنوان یک مقدار واقعی در دیتاسنترها و برنامه‌ها استفاده می‌کنیم. این بارگذاری بیش از حد روی یک مقدار، گاهی اوقات برنامه‌نویسان را با چالش‌های جدی روبه‌رو می‌کند.

چرا None دردسرساز می‌شود؟

مشکلات ناشی از ابهام None در سناریوهای مختلفی بروز پیدا می‌کنند:

  • کش‌کردن داده‌ها: یک کش ساده ممکن است None را هم برای کلیدی که اصلاً وجود ندارد برگرداند و هم برای کلیدی که مقدار ذخیره‌شده‌ی آن برابر با None است.
  • پارامترهای تنظیمات: در یک تابع، مقدار timeout=None آیا به معنای «بدون محدودیت زمانی» است یا «حفظ مقدار فعلی»؟
  • مدیریت خطا: تابعی که خطای TimeoutError را صید کرده و None برمی‌گرداند، از آن به عنوان سیگنال خطا استفاده می‌کند.

استفاده از مقدار Sentinel به عنوان یک نگهبان خارج از دامنه‌ی مقادیر معتبر، این تداخل‌ها را از بین می‌برد.

ردپای Sentinel در پایتون

پایتون خودش به شکل‌های مختلف از Sentinelها استفاده می‌کند:

  • مقدار Ellipsis (...) برای رد کردن ابعاد در برش‌های NumPy و نشانه‌گذاری استاب‌ها.
  • مقدار NotImplemented برای مشخص کردن اینکه محاسبه باید در جای دیگری انجام شود.
  • مقدار MISSING در پایتون برای تفکیک فیلدی که صراحتاً null تنظیم شده با فیلدی که اصلاً ارسال نشده است.

ساخت Sentinel سفارشی و چالش‌های تایپینگ

ساخت Sentinel دستی در گذشته با ترفندهایی مثل MISSING = object() انجام می‌شد که در زمان اجرا به خوبی کار می‌کند اما تایپ‌چکرها (Static Type Checkers) را با مشکل مواجه می‌کند. روش‌های جایگزین مانند TypeIs، رشته‌های Literal یا الگوهای Enum نیز هرکدام با معایب و پیچیدگی‌هایی همراه بودند.

راه‌حل جدید در پایتون

پس از ارائه‌ی پیشنهادها و چالش‌های فراخوانی استاندارد (مانند PEP 661)، از نسخه‌ی پایتون ۳.۱۵ به بعد، امکان استفاده از sentinel به صورت توکار (Built-in) فراهم شده است. به این ترتیب تایپ‌چکرها می‌توانند آن را به راحتی مدیریت کنند:

MISSING = sentinel("MISSING")

def update_email(user_id: int, email: str | None | MISSING = MISSING) -> None:
    if email is MISSING:
        return
    elif email is None:
        db.delete_email(user_id)
    else:
        db.set_email(user_id, email.lower())

دیدگاه برنامه‌نویسان در هکرنیوز

در بحث‌های هکرنیوز، برخی کاربران به شباهت این مفهوم با تفاوت بین null و undefined در JavaScript یا مقدار nil در Lua اشاره کردند. همچنین برخی یادآور شدند که طراحی تابع کش باید به جای بازگرداندن None برای کلید ناموجود، خطای مناسب صادر کند.

نتیجه‌گیری

آگاهی از ابهامات None به توسعه‌دهندگان کمک می‌کند کدهای خواناتر و کم‌خطاتری بنویسند. با آمدن Sentinelهای رسمی به پایتون، نیازی به ترفندهای پیچیده‌ی قدیمی نیست و می‌توانیم نیت کدهای خود را با دقت بیشتری بیان کنیم.

این مطلب به‌صورت کاملاً خودکار و با هوش مصنوعی از مقالهٔ اصلی و بحث هکرنیوز تهیه شده و ممکن است خطا داشته باشد. حقوق مطلب اصلی متعلق به نویسندهٔ آن است. قوانین و گزارش مشکل

این خبر را با دیگران به اشتراک بگذارید

خبرهای فناوری در قالب پست و ویدیوی کوتاه، در اینستاگرام هکرنیوز بلاگ. به‌زودی
هر خبر به محض انتشار، به‌همراه پادکست روزانه در کانال تلگرام هکرنیوز بلاگ.