سلام و پایتون یک هدف مشترک دارند: کدی کوتاه و خوانا. اما از دو راه مخالف به آن میرسند. پایتون زبانی با گونههای پویاست و معمولاً روی مفسر اجرا میشود؛ زبان برنامهنویسی سلام گونههای ایستا دارد و به کد ماشین بومی کامپایل میشود. در سنجش (Benchmark) پروژه روی ۳۹ برنامهی کوچک که در همهی زبانها الگوریتم یکسانی دارند، پایتون حدود ۵۶ برابر سلام زمان برد. در عوض، پایتون یکی از بزرگترین اکوسیستمهای کتابخانه را در میان همهی زبانها دارد، شیوهی کار تعاملیای که دانشمندان داده به آن تکیه میکنند، و چند دهه آموزش، پرسش و پاسخ و تجربهی محیط عملیاتی. سلام کتابخانهی استاندارد گستردهای دارد و جامعهای کوچک.
پس سلام جایگزینی نیست که بیدردسر جای پایتون بنشیند. گزینهای است برای آن بخشهایی از یک پروژه که سرعت پایتون، مصرف حافظه یا شیوهی استقرارش دستوپاگیر میشود، با نحوی که یک برنامهنویس پایتون از همان روز اول میتواند بخواند.
مقایسه سلام و پایتون در یک نگاه
| پایتون | سلام | |
|---|---|---|
| اجرا | بایتکد تفسیری (CPython)؛ پیادهسازیهای دیگری مثل PyPy هم هست | کامپایل پیش از اجرا به کد بومی؛ یک مفسر (salam exec) برای اجرای سریع |
| گونهها | پویا؛ راهنمای گونهی اختیاری (type hints) که ابزارهای بیرونی بررسیاش میکنند | ایستا با استنتاج گونه، بررسیشده به دست کامپایلر |
| بلوکها | تورفتگی | دونقطه بلوک را باز میکند و پایان (end) آن را میبندد |
| حافظه | شمارش ارجاع بههمراه یک جمعآور چرخهها | دستی: آزادکن() و دیرکن، با بررسیهای زمان کامپایل |
| موازیسازی | GIL در ساخت پیشفرض؛ ساخت اختیاری بدون GIL (آزمایشی در ۳٫۱۳، پشتیبانیشده در ۳٫۱۴) | نخهای سیستمعامل، استخر کار، کانال، عملیات اتمی |
| سرعت در سنجش | حدود ۵۶ برابر زمان سلام | در ردهی C و Rust |
| استقرار | مفسر بههمراه وابستگیها، یا یک بستهساز | یک فایل اجرایی بومی |
| اکوسیستم | عظیم: PyPI، NumPy، pandas، PyTorch، Django، Jupyter | کتابخانهی استاندارد بزرگ، بستههای شخص ثالث اندک |
| زبان کد منبع | واژههای کلیدی انگلیسی | واژههای کلیدی انگلیسی یا فارسی، با یک کامپایلر |
یک برنامه در هر دو زبان
واژههای یک جمله را بشمارید و سه واژهی پرتکرار را چاپ کنید: پرتکرارترین اول، و در صورت تساوی به ترتیب الفبا. پایتون با collections.Counter این کار را در چند خط انجام میدهد:
from collections import Counter
text = "the cat sat on the mat and the dog sat on the log"
counts = Counter(text.split())
top = sorted(counts.items(), key=lambda kv: (-kv[1], kv[0]))[:3]
for word, n in top:
print(word, n)سلام گونهای مثل Counter برای این کار ندارد. پس برنامه شمارشها را در یک نگاشت (HashMap) جمع میکند، آنها را به یک وکتور از ساختارها منتقل میکند و با یک تابع مقایسه مرتب میکند. جملهی ورودی را عمداً انگلیسی نگه داشتهایم تا خروجی دو برنامه دقیقاً قابل مقایسه باشد:
واردسازی مرتب سازی
واردسازی رشته
ساختار مدخل:
همگانی واژه: رشته
همگانی شمار: صحیح
پایان
تابع ریشه:
متن := "the cat sat on the mat and the dog sat on the log"
واژهها := رشته.واژه ها(متن)
دیرکن واژهها.آزادکن()
ناپایا شمارش := نگاشت {} برگردان نگاشت<رشته، صحیح>
دیرکن شمارش.آزادکن()
هر کلمه در واژهها:
شمارش.درج(کلمه، شمارش.دریافت با پیش فرض(کلمه، ۰) + ۱)
پایان
ناپایا مدخلها := وکتور {} برگردان وکتور<مدخل>
دیرکن مدخلها.آزادکن()
هر کلمه، تعداد در شمارش:
مدخلها.بیفزا(مدخل { واژه = کلمه، شمار = تعداد })
پایان
مرتب سازی.مرتب سازی با(مدخلها، (الف: مدخل، ب: مدخل):
اگر الف.شمار != ب.شمار: برگشت الف.شمار > ب.شمار پایان
برگشت رشته.مقایسه(الف.واژه، ب.واژه) < ۰
پایان)
تکرار ۳ در ای:
م := مدخلها.بگیر(ای)
سرچاپ م.واژه، م.شمار
پایان
پایانهر دو برنامه همان سه خط را چاپ میکنند. نسخهی سلام بلندتر است و دلیلهایش را باید گفت: گونهها روی ساختار اعلام میشوند، ظرفها با دیرکن آزاد میشوند و گونهی آمادهای برای شمارش وجود ندارد. از سوی دیگر، بخش زیادی از آن برای برنامهنویس پایتون آشناست: هر کلمه در واژهها همان for w in words است، هر کلمه، تعداد در شمارش همان for w, n in counts.items()، و تکرار ۳ در ای همان for i in range(3)؛ آکولاد و نقطهویرگول هم در کار نیست. سرچاپ حتی مثل print پایتون آرگومانهایش را با فاصله کنار هم چاپ میکند.
گونههای ایستا در برابر گونههای پویا
در پایتون، اشتباه گونه وقتی پیدا میشود که همان خط اجرا شود:
def discount(price, percent):
return price * (100 - percent) / 100
print(discount(80.0, 15)) # 68.0
print(discount(80.0, "15")) # TypeError: unsupported operand type(s) for -: 'int' and 'str'در سلام همین اشتباه هرگز به برنامهی در حال اجرا نمیرسد. نسخهی درست:
تابع تخفیف(قیمت: اعشار۶۴، درصد: اعشار۶۴): اعشار۶۴:
برگشت قیمت * (۱۰۰.۰ - درصد) / ۱۰۰.۰
پایان
تابع ریشه:
سرچاپ تخفیف(۸۰.۰، ۱۵.۰)
پایاناگر فراخوانی را به تخفیف(۸۰.۰، "15") تغییر دهید، salam check با این پیام متوقف میشود و به همان خط اشاره میکند:
خطا[خطا۰۱۲]: آرگومان ۲: نمیتوان 'رشته' را به 'اعشار۶۴' پاس دادپایتون با راهنمای گونه و ابزاری مانند mypy یا Pyright میتواند به این نزدیک شود و بسیاری از تیمها دقیقاً همین کار را میکنند؛ در سلام این بررسی بخشی از کامپایلر است و نمیشود از آن گذشت. گونهی متغیرهای محلی استنتاج میشود (شمار := ۰ یک عدد صحیح است و نام := "سارا" یک رشته)، پس گونههایی که مینویسید بیشتر روی پارامترهای تابع و فیلدهای ساختار است. بهایش انعطاف است: duck typing در زمان اجرا و monkey patching وجود ندارد، و دادهی ناهمگون کمی تشریفات بیشتر میخواهد که سلام آن را با میانجیها، گونههای عام (Generics) و گونههای «یا» مانند صحیح یا رشته (int or str) پوشش میدهد. نوشتهی گونههای ایستا سیستم گونهی سلام را شرح میدهد.
زبان سلام چقدر از پایتون سریعتر است؟
در سنجشی که در صفحهی سرعت منتشر شده، میانگین هندسی ۳۹ برنامهی همالگوریتم برای سلام ۱۰٫۶ میلیثانیه و برای پایتون ۵۹۸ میلیثانیه بود؛ یعنی پایتون حدود ۵۶ برابر زمان برد. این یکی از همان برنامههاست، 04_collatz، که در میان عددهای کوچکتر از ۳۰٬۰۰۱ عددی را پیدا میکند که طولانیترین دنبالهی کولاتز را دارد. کد پایتونِ سنجش:
best_steps = 0
best_n = 1
for n in range(1, 30001):
m = n
c = 0
while m != 1:
if m % 2 == 0:
m = m // 2
else:
m = 3 * m + 1
c += 1
if c > best_steps:
best_steps = c
best_n = n
print(best_steps)
print(best_n)و کد سلامِ همان پوشه، اینجا به فارسی برگردانده شده:
تابع ریشه:
ناپایا بیشترین گام := ۰ برگردان صحیح۶۴
ناپایا بهترین عدد := ۱ برگردان صحیح۶۴
ناپایا ن := ۱ برگردان صحیح۶۴
تا ن <= ۳۰۰۰۰:
ناپایا م := ن
ناپایا گام := ۰ برگردان صحیح۶۴
تا م != ۱:
اگر م % ۲ == ۰:
م /= ۲
وگرنه:
م = ۳ * م + ۱
پایان
گام++
پایان
اگر گام > بیشترین گام:
بیشترین گام = گام
بهترین عدد = ن
پایان
ن++
پایان
سرچاپ بیشترین گام
سرچاپ بهترین عدد
پایاناین دو تقریباً خط به خط یکیاند. در سلام تا شرط: حلقهای است که تا وقتی شرط برقرار است اجرا میشود، درست مثل while، و نامها میتوانند فاصله داشته باشند، مانند بیشترین گام. پایتون ۲۴۵٫۷ میلیثانیه طول کشید و سلام ۳٫۷ میلیثانیه. دلیلش ساختاری است، نه ترفندی زیرکانه: CPython بایتکد اجرا میکند و با اشیای عدد صحیحِ بستهبندیشده (boxed) کار میکند، در حالی که سلام حلقه را به دستورهای ماشین روی عددهای صحیح ۶۴ بیتی کامپایل میکند.
دو نکته این مقایسه را منصفانه نگه میدارد. اول، برنامهها کوتاهاند، پس زمان راهاندازی مفسر هم جزو زمان پایتون است و نسبت از برنامهای به برنامهی دیگر فرق میکند: در فیبوناچی بازگشتی حدود ۱۹ برابر بود و در بازی زندگی نزدیک به هزار برابر. دوم، کد واقعی پایتون که کار عددی سنگین انجام میدهد کتابخانههایی را صدا میزند که با C نوشته شدهاند. برنامههای ۴۰ تا ۴۲ این مجموعه در پایتون از NumPy و در سلام از بستههای matrix و tensor استفاده میکنند: پایتون ضرب ماتریس ۴۰۰ در ۴۰۰ را در ۱۲۱٫۸ میلیثانیه تمام کرد، سلام در ۱۴٫۳ میلیثانیه و حلقههای دستنویس C در ۴۲٫۵ میلیثانیه. پایتون با NumPy در فاصلهی چند برابری کد کامپایلشده میماند؛ بدون آن، یک تا دو مرتبهی بزرگی عقب است. نوشتهی سنجش روش کار و محدودیتهایش را توضیح میدهد.
شکاف اکوسیستم
اینجاست که پایتون برنده است، آن هم با فاصلهی زیاد. PyPI صدها هزار بسته دارد. علم داده روی NumPy، pandas، SciPy و Jupyter میچرخد؛ یادگیری ماشین روی PyTorch، scikit-learn و کتابخانههای Hugging Face؛ بکاند وب روی Django، Flask و FastAPI؛ و تقریباً هر سرویس ابری، پایگاه داده و API اول از همه یک کلاینت پایتون منتشر میکند. پاسخ تقریباً هر پرسشی دربارهی پایتون با یک جستجو پیدا میشود و بیشتر برنامهنویسها کمی پایتون بلدند.
کتابخانهی استاندارد سلام برای زبانی به این جوانی بهطور غیرعادی گسترده است: سرور و کلاینت HTTP، مسیریاب، WebSocket، gRPC، درایور برای SQLite، PostgreSQL، MySQL، Redis و ClickHouse، JSON و CSV، رمزنگاری، فشردهسازی، تصویر، صدا، و اجزای پایهی یادگیری ماشین مانند تانسور، مشتقگیری خودکار، لایههای شبکهی عصبی و بارگذاری مدلهای ONNX و GGUF. این کتابخانه همراه کامپایلر نصب میشود، پس بسیاری از برنامهها به هیچ کد شخص ثالثی نیاز ندارند. اما بستههای شخص ثالث اندکاند، چیزی همعمق پشتهی علمی پایتون وجود ندارد و جامعهای که آموزش مینویسد و به پرسشها پاسخ میدهد کوچک است. برای یادگیری ماشین بهطور خاص، نوشتهی یادگیری ماشین آنچه را هست شرح میدهد و نوشتهی سلام در برابر پایتون و جولیا بخش عددی را مقایسه میکند.
حافظه و موازیسازی
پایتون حافظه را با شمارش ارجاع و یک جمعآور چرخه برایتان مدیریت میکند و همین بخش بزرگی از دلیل خوشایند بودن نوشتن پایتون است. سلام زبالهروب (Garbage Collector) ندارد: ظرفها با آزادکن() آزاد میشوند، معمولاً از راه دیرکن (defer)، و تابعی که رشته یا ظرف تازهای برمیگرداند مالکیت آن را به فراخواننده میسپارد. کامپایلر اشتباههای رایجی مانند استفاده پس از آزادسازی را گزارش میکند، اما آزادسازیِ فراموششده یعنی نشت حافظه. در عوض، مصرف حافظهی یک برنامهی سلام همان چیزی است که تخصیص میدهد، بدون زبالهروب و بدون اشیای بستهبندیشده برای عددهای ساده.
برای کار موازیِ پردازندهمحور، ساخت پیشفرض CPython قفل سراسری مفسر (GIL) دارد، پس نخها کد پایتون را بهطور موازی اجرا نمیکنند؛ پاسخهای معمول multiprocessing، افزونههای بومی یا ساخت اختیاری بدون GIL است (پشتیبانیشده از پایتون ۳٫۱۴). نخهای سلام روی همهی هستهها موازی اجرا میشوند و استخر.برای موازی (pool.ParallelFor)، استخر.نگاشت موازی (pool.Map) و واژهی کلیدی برو (go) کار را میان آنها پخش میکنند، با قفل (mutex)، عملیات اتمی و کانال برای هماهنگی. نوشتهی همزمانی نمونههایی دارد.
روند کار: اسکریپت، REPL و نوتبوک
چرخهی ویرایش و اجرا در پایتون فوری است و نوتبوکها کار اکتشافی را تعاملی میکنند. سلام بخشی از این حس را نگه میدارد. salam run file.salam در یک گام کامپایل و اجرا میکند و فایلی به جا نمیگذارد، salam exec وقتی ابزار کامپایل C در دسترس نیست برنامه را با مفسر داخلی اجرا میکند، و salam cli یک محیط تعاملی (REPL) باز میکند. ویرایشگر آنلاین برنامهها را در یک زبانهی مرورگر اجرا میکند. محیط نوتبوکی همپای Jupyter وجود ندارد و کامپایل پیش از هر اجرا تأخیر کوتاهی اضافه میکند. نوشتهی salam run در برابر salam build گزینهها را توضیح میدهد.
در سوی دیگر، استقرار به سود سلام است: salam build یک فایل اجرایی بومی میسازد که روی ماشین مقصد نه مفسر میخواهد، نه محیط مجازی پایتون (virtual environment) و نه نصب وابستگی.
سلام یا پایتون: کدام را انتخاب کنیم؟
پایتون را انتخاب کنید وقتی:
- کار تحلیل داده، محاسبات علمی یا یادگیری ماشین است و به NumPy، pandas، PyTorch و همخانوادههایشان تکیه دارد؛
- کد چسب، خودکارسازی یا نمونهی اولیه مینویسید و سرعت توسعه از زمان اجرا مهمتر است؛
- کتابخانهها، نیروی کار قابل استخدام یا تجربهی تیمی که لازم دارید در پایتون است؛
- بهصورت تعاملی در نوتبوک کار میکنید.
سلام را انتخاب کنید وقتی:
- بخشی پردازندهمحور از برنامه در پایتون خالص بیش از حد کند است و ترجیح میدهید سراغ C نروید؛
- یک فایل اجرایی بومی برای استقرار، مصرف حافظهی کم و راهاندازی سریع میخواهید؛
- میخواهید خطاهای گونه پیش از اجرای برنامه گرفته شوند؛
- زبانی کامپایلی و خوانا برای آموزش میخواهید، از جمله به فارسی، چون هر واژهی کلیدی و هر پیام خطا به هر دو زبان وجود دارد (یک زبان، دو خط).
بسیاری از پروژهها از هر دو استفاده خواهند کرد: پایتون برای کاوش و هماهنگسازی، و یک زبان کامپایلی برای مسیر داغ (hot path) یا سرویسی که مستقر میشود.
پرسشهای پرتکرار
آیا زبان سلام از پایتون سریعتر است؟
بله، در کدهای پردازندهمحور با فاصلهی زیاد. در سنجش ۳۹ برنامهای پروژه، پایتون حدود ۵۶ برابر سلام زمان برد (میانگین هندسی ۵۹۸ میلیثانیه در برابر ۱۰٫۶). وقتی NumPy کار سنگین را انجام دهد، فاصلهی پایتون با کد کامپایلشده به چند برابر کم میشود.
یادگیری زبان سلام برای برنامهنویس پایتون آسان است؟
بیشتر بله. حلقهها، شرطها و چاپ شبیهاند، آکولاد و نقطهویرگول ندارد و گونهی متغیرهای محلی استنتاج میشود. بخشهای تازه اینهاست: گونههای اعلامشده روی تابعها و ساختارها، پایان به جای تورفتگی، و آزاد کردن حافظهی هیپ با دیرکن فهرست.آزادکن().
آیا سلام میتواند جای پایتون را در علم داده بگیرد؟
امروز نه. سلام تانسور، ماتریس، آمار و اجزای پایهی شبکهی عصبی دارد، اما چیزی نزدیک به عمق NumPy، pandas، SciPy، PyTorch و Jupyter ندارد. برای سریعتر کردن بخشهای مشخص یا استقرار ابزارهای آماده مناسبتر است.
آیا سلام مثل پایتون REPL دارد؟
بله. salam cli یک محیط تعاملی باز میکند، salam exec یک فایل را با مفسر اجرا میکند و ویرایشگر آنلاین کد را در مرورگر اجرا میکند. محیط نوتبوکی مانند Jupyter وجود ندارد.