کتابخانه types در پایتون
ماژول types در پایتون مجموعهای از تعاریف نوعها (type objects) و ابزارهایی فراهم میکند که برای بررسی نوعهای داخلی، ساخت انواع تابعی دینامیک و بایند کردن متدها مفید هستند. این ماژول بهویژه برای برنامهنویسانی که با متاپروگرامینگ، تستنویسی یا ایجاد تکنیهای پویا سر و کار دارند کاربردی است.
چرا از types استفاده کنیم؟
- بررسی دقیقتر نوعها بهجای مقایسه نام نوع در متن.
- ساخت اشیاء توصیفی ساده مانند SimpleNamespace.
- بایند کردن تابع به نمونه با MethodType.
- ایجاد viewهای فقط-خواندنی از دیکشنری با MappingProxyType.
- تمایز بین حالتهای تابع، متد، ژنراتور، کرoutine و غیره با ثبات بیشتر.
موارد متداول در ماژول types
در ادامه فهرستی از شناختهشدهترین نمادها در types آمده است:
| نماد | شرح |
|---|---|
| FunctionType / LambdaType | اشاره به توابع معمولی پایتون |
| MethodType | برای بایند کردن توابع به نمونهها بهصورت متد |
| ModuleType | نوع ماژولها |
| GeneratorType | نوع شیء تولیدشده توسط توابع yield |
| CoroutineType | نوع کرoutineها (async def) |
| MappingProxyType | view فقطخواندنی از دیکشنری |
| 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']) # 99MappingProxyType یک 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 برای بررسی دقیقتر نوع استفاده کنید. دانستن این ابزارها موجب نوشتن کد انعطافپذیرتر، دقیقتر و قابلاعتمادتر میشود.
آیا این مطلب برای شما مفید بود ؟




