ویژگی تصویر

کتابخانه types در پایتون — معرفی، کاربردها و نمونه‌های عملی

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

ماژول types در پایتون مجموعه‌ای از تعاریف نوع‌ها (type objects) و ابزارهایی فراهم می‌کند که برای بررسی نوع‌های داخلی، ساخت انواع تابعی دینامیک و بایند کردن متدها مفید هستند. این ماژول به‌ویژه برای برنامه‌نویسانی که با متاپروگرامینگ، تست‌نویسی یا ایجاد تکنیهای پویا سر و کار دارند کاربردی است.

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

  • بررسی دقیق‌تر نوع‌ها به‌جای مقایسه نام نوع در متن.
  • ساخت اشیاء توصیفی ساده مانند SimpleNamespace.
  • بایند کردن تابع به نمونه با MethodType.
  • ایجاد viewهای فقط-خواندنی از دیکشنری با MappingProxyType.
  • تمایز بین حالت‌های تابع، متد، ژنراتور، کرoutine و غیره با ثبات بیشتر.

موارد متداول در ماژول types

در ادامه فهرستی از شناخته‌شده‌ترین نمادها در types آمده است:

نمادشرح
FunctionType / LambdaTypeاشاره به توابع معمولی پایتون
MethodTypeبرای بایند کردن توابع به نمونه‌ها به‌صورت متد
ModuleTypeنوع ماژول‌ها
GeneratorTypeنوع شیء تولیدشده توسط توابع yield
CoroutineTypeنوع کرoutineها (async def)
MappingProxyTypeview فقط‌خواندنی از دیکشنری
SimpleNamespaceشی سبک برای نگهداری صفات (attributes)

نمونه‌ها و توضیحات عملی

در ادامه چند مثال عملی که نشان‌دهندهٔ مزایای استفاده از types هستند را بررسی می‌کنیم.

from types import SimpleNamespace

ns = SimpleNamespace(x=10, y=20)
print(ns.x, ns.y)  # دسترسی مشابه اشیاء با صفات
ns.z = 30
print(ns)  # SimpleNamespace(x=10, y=20, z=30)

در این کد، SimpleNamespace شیئی سبک برای نگهداری داده‌هاست که مشابه یک شیء با صفات (attributes) عمل می‌کند. مناسب برای برگشت ساختارهای ساده از توابع یا نگهداری تنظیمات.

from types import MethodType

class A:
    def __init__(self, name):
        self.name = name

def greet(self, who):
    return f"{self.name} greets {who}"

a = A("Alice")
a.greet = MethodType(greet, a)
print(a.greet("Bob"))  # Alice greets Bob

در این مثال، تابع عادی greet به‌صورت متد به نمونهٔ a بایند شده است. این تکنیک زمانی مفید است که بخواهیم به‌صورت داینامیک رفتار نمونه‌ها را تغییر دهیم یا متدهایی را در زمان اجرا اضافه کنیم.

from types import MappingProxyType

data = {'a': 1, 'b': 2}
readonly = MappingProxyType(data)
print(readonly['a'])  # 1
# readonly['a'] = 100  # خطا: TypeError
data['a'] = 99
print(readonly['a'])  # 99

MappingProxyType یک view فقط‌خواندنی از دیکشنری ایجاد می‌کند. توجه داشته باشید که اگر دیکشنری پایه تغییر کند، view تغییر را منعکس می‌کند؛ اما تلاش برای تغییر از طریق view باعث خطا خواهد شد. این ابزار برای محافظت از API در برابر تغییر بی‌قصد یا ناخواسته مفید است.

from types import GeneratorType

def gen():
    yield 1

g = gen()
print(isinstance(g, GeneratorType))  # True

با استفاده از GeneratorType می‌توان مطمئن شد که شیء مورد بررسی واقعاً یک ژنراتور است؛ این دقت در موقعیت‌هایی مثل تست‌ها یا فریم‌ورک‌ها که رفتار بر اساس نوع داخلی متفاوت است، اهمیت دارد.

ایجاد تابع دینامیک با FunctionType

گاهی لازم است تابعی در زمان اجرا ایجاد شود. می‌توان از types.FunctionType استفاده کرد، هرچند این کار نیازمند درک ساختار code object است. برای نمونهٔ ساده‌تر می‌توان از exec استفاده کرد، اما نمونهٔ مستقیم با FunctionType مشابه این است:

import types

code = compile('def f(x):n    return x + 1n', '', 'exec')
ns = {}
exec(code, ns)
f = ns['f']
print(f(10))  # 11

در این رویکرد از compile و exec استفاده شده تا تابعی در فضای نام دلخواه تعریف شود؛ سپس آن را مانند هر تابع دیگری فراخوانی می‌کنیم. ایجاد مستقیم FunctionType پیچیده‌تر است اما در سناریوهای خاص و برای ساختن توابع با code object سفارشی کاربرد دارد.

تفاوت types با typing و استفاده‌های پیشنهادی

  • types برای کار با اشیاء در زمان اجرا و نوع‌های داخلی استفاده می‌شود.
  • typing بیشتر برای اعلان نوع‌ها (type hints) در زمان توسعه و ابزارهای استاتیک کاربرد دارد.

در عمل، از types برای متاپروگرامینگ، تست‌های دقیق، بایند کردن متدهای داینامیک و محافظت از داده‌ها با MappingProxyType استفاده کنید. از typing برای مستندسازی و static analysis بهره ببرید.

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

  • به جای مقایسه نام نوع (مثلاً type(obj).__name__ == 'function') از نمادهای types استفاده کنید تا کد قابل‌تر و مقاوم‌تر باشد.
  • MappingProxyType برای APIهایی که می‌خواهند دیکشنری ورودی را منتشر کنند بدون اینکه امکان تغییر خارجی فراهم کنند، گزینهٔ کم‌هزینه‌ای است.
  • برای افزودن رفتار داینامیک به کلاس‌ها، ترجیحاً از الگوهای طراحی یا mixinها استفاده کنید؛ MethodType زمانی مناسب است که تغییر در سطح نمونه موردنیاز باشد.
  • هنگام ساخت توابع دینامیک احتیاط کنید: مشکلات امنیتی (اجرای کد ناآشنا) و اشکال‌زدایی دشوار ممکن است رخ دهد.

خلاصه

ماژول types ابزارهای مهمی برای کار با نوع‌های داخلی پایتون و انجام عملیات داینامیک در زمان اجرا فراهم می‌کند. از SimpleNamespace برای ساخت اشیاء سبک، از MethodType برای بایند کردن متدها، از MappingProxyType برای ارائه viewهای فقط‌خواندنی و از ثابت‌های نوعی مثل GeneratorType و FunctionType برای بررسی دقیق‌تر نوع استفاده کنید. دانستن این ابزارها موجب نوشتن کد انعطاف‌پذیرتر، دقیق‌تر و قابل‌اعتمادتر می‌شود.

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

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