PyCoders (پایتون)
4.1K subscribers
979 photos
148 videos
69 files
238 links
◇ #پایتون جادوگر دنیای برنامه نویسی!
◇ معرفی حوزه های کاری پایتون
◇ معرفی کتابخونه های کاربردی
◇ معرفی دوره های مفید
◇ معرفی تکنیک ها و نکات
◇ نقشه راه حوزه های مختلف
◇ اخبار و آپدیت های پایتون
◇ و هر چیزی در مورد پایتون!

■ گروه پایتون:
@programmers_py
Download Telegram
🔆 مدیریت منابع با contextlib

🔹 از تکرار try...finally برای بستن فایل‌ها و اتصال‌ها خسته شدی؟

🔹 پایتون ابزاری به نام Context Manager داره که با دستور with استفاده میشه. اما اگر بخوای خودت یک Context Manager سفارشی بسازی، نیازی نیست حتماً کلاس با متدهای enter و exit بنویسی!
با ماژول contextlib و دکوراتور @contextmanager می‌تونی خیلی تمیز این کار رو انجام بدی:

from contextlib import contextmanager

@contextmanager
def managed_resource():
print("-> باز کردن اتصال/فایل")
yield "Resource Object"
print("-> بستن ایمن اتصال/فایل")

# استفاده:
with managed_resource() as res:
print(f"در حال کار با: {res}")

🐍 @python_rd
🔆 خروجی این تکه کد چیه؟

def add_item(item, lst=[]):
lst.append(item)
return lst

print(add_item(1))
print(add_item(2))
print(add_item(3, [9, 9]))
print(add_item(4))

🔹گزینه‌ها:

الف) [1], [2], [9, 9, 3], [4]
ب) [1], [1, 2], [9, 9, 3], [1, 2, 4]
ج) [1], [2], [3], [4]

🐍 @python_rd
🔆 چرا برای داده‌های حجیم نباید از return استفاده کنی؟

🔹 وقتی یک تابع لیست بزرگی از داده‌ها رو با return برمی‌گرداند، کل داده‌ها باید همزمان توی رم (RAM) لود بشن که باعث مصرف شدید حافظه و کندی سیستم میشه.

🔹 اما اگر به جای return از yield استفاده کنی، تابع تبدیل به یک Generator میشه که داده‌ها رو به صورت تک‌به‌تک و تنبل (Lazy Evaluation) تولید می‌کنه:

def read_large_file(file_path):
with open(file_path, 'r') as f:
for line in f:
yield line.strip() # هر بار فقط یک خط را در حافظه نگه می‌دارد

🔹با این روش می‌تونی فایل‌های چند گیگابایتی رو با مصرف چند مگابایت رم پردازش کنی!

🐍 @python_rd
🔆 مدیریت تمیز منابع با Context Managerهای سفارشی (contextlib)

🔹 ساخت Context Managerها معمولاً با نوشتن کلاس و متدهای enter و exit انجام می‌شود. اما با دکوراتور contextmanager@ از ماژول contextlib می‌توانید این کار را خیلی سریع‌تر و پایتونیک‌تر انجام دهید.

from contextlib import contextmanager
import time


@contextmanager
def measure_time(task_name: str):
start_time = time.perf_counter()
print(f"--- شروع: {task_name} ---")
try:
yield # کنترل اجرا در این نقطه به بدنه with منتقل می‌شود
finally:
elapsed = time.perf_counter() - start_time
print(f"--- پایان: {task_name} | زمان اجرا: {elapsed:.4f} ثانیه ---\n")


# استفاده کاربردی
with measure_time("پردازش سنگین داده‌ها"):
# شبیه‌سازی یک کار سنگین
total = sum(i**2 for i in range(10_000_000))
print(f"نتیجه محاسبات: {total}")

🐍 @python_rd
🔆 حذف تاریخی GIL از پایتون (Free-threaded Python)

🔹 یک رویداد تاریخی: حذف قفل مفسر (GIL) از هسته CPython رسماً کلید خورد!

🔹 سرانجام پس از سال‌ها بحث و مناظره در بنیاد نرم‌افزار پایتون (PSF)، طرح PEP 703 (معروف به Free-threaded CPython) تصویب و گام‌های اجرایی آن آغاز شد. با این تغییر، مفسر پایتون می‌تواند از تمام هسته‌های پردازنده (Multi-Core CPU) در Multi-threading به صورت واقعی بهره ببرد بدون اینکه گلوگاه قفل مفسر سر راهش باشد.

🔹 نکات کلیدی این تحول:

▪️ پشتیبانی اولیه به صورت بیلد آزمایشی (Experimental / --disable-gil) در دسترس قرار گرفته است.

▪️ تیم‌های توسعه کتابخانه‌های بزرگ مانند NumPy و PyTorch در حال بازنویسی بخش‌های C-API خود برای سازگاری با حالت بدون GIL هستند.

▪️ طبق پیش‌بینی هسته مرکزی، پایتون در پردازش‌های سنگین موازی تا چند برابر افزایش کارایی را تجربه خواهد کرد.

🔹 منبع رسمی:

• مستندات رسمی PEP 703: peps.python.org/pep-0703
• اعلامیه Steering Council پایتون: discuss.python.org

🐍 @python_rd
🔆 راز مکانیزم پیاده‌سازی و تغییر جهت NaN در الگوریتم مرتب‌سازی پایتون (Timsort)

🔹 باگ ریاضیاتی پنهان: چرا پایتون هیچ‌وقت نمی‌تواند لیستی از NaNها را مرتب کند؟!

🔹 در پایتون، مقدار float('nan') (Not a Number) خصوصیت عجیبی دارد:

nan طبق استاندارد IEEE-754 با خودش هم برابر نیست!
float('nan') == float('nan') ⬅️ خروجی False است!
float('nan') < 5 ⬅️ باز هم False است!

🔹 حالا شگفتی ماجرا در متد .sort() پایتون است:

الگوریتم مرتب‌سازی CPython یعنی Timsort بر اصل تقارن و ترتیبی بودن مقایسه‌ها استوار است. اگر شما لیستی شامل اعداد و NaN را با .sort() مرتب کنید:


🔹 نتیجه خروجی به ترتیب قرارگیری اولیه عناصر بستگی دارد و غیرقابل‌پیش‌بینی است!

🔹 پایتون هیچ خطایی (Error) raise نمی‌کند، اما خروجی نهایی مرتب‌شده نخواهد بود!

🔹 مهندسان CPython سال‌هاست که در گیت‌هاب پایتون روی این موضوع بحث دارند و تصمیم گرفته‌اند برای حفظ پرفورمنس Timsort، هیچ لایه اعتبارسنجی اضافی اضافه نکنند و این مسئولیت را روی دوش برنامه‌نویس بگذارند!

🐍@python_rd
کوییز پایتون

🔆 خروجی اجرای کد زیر چیست؟

t = (1, 2, [3, 4])

try:
t[2] += [5]
except TypeError:
pass

print(t)

🔹 گزینه‌ها:

1️⃣ (1, 2, [3, 4])
2️⃣ (1, 2, [3, 4, 5])
3️⃣ خطای مدیریت‌نشده رخ می‌دهد و برنامه متوقف می‌شود
4️⃣ خروجی (1, 2, [5]) خواهد بود


🐍@python_rd
🔆 یک تله عجیب در پایتون: bool در واقع زیرکلاس int است

🔹 خیلی‌ها می‌دانند True == 1 و False == 0، اما نکته عجیب‌تر اینجاست که:

print(isinstance(True, int))   # True
print(True + True) # 2
print(False + 10) # 10

🔹 این یعنی:

True و False فقط مقدار بولی نیستند

در سطح type system، از int ارث‌بری می‌کنند

🔹 این رفتار در خیلی از سناریوها مفید است، ولی اگر روی counting، hashing یا data processing کار کنی، گاهی می‌تواند نتایج عجیبی بسازد.

🐍 @python_rd
❤4
🔆 آیا enumerate() بهتر از index-based loop است؟

🔹 خیلی‌ها هنوز این شکلی می‌نویسند:

items = ["apple", "banana", "orange"]

for i in range(len(items)):
print(i, items[i])

🔹 ولی راه پایتونیک‌تر:

items = ["apple", "banana", "orange"]

for index, value in enumerate(items):
print(index, value)

🔹 اگر index را از 1 بخواهی:

for index, value in enumerate(items, start=1):
print(index, value)

🔹 چرا بهتر است؟

خواناتر است

خطای index کمتر می‌شود

پایتونیک‌تر و حرفه‌ای‌تر است

🔹 این از آن تفاوت‌های کوچک است که کیفیت کد را در بلندمدت خیلی بالا می‌برد.

🐍 @python_rd
🌐 خروجی این کد پایتون چیست؟

x = [1, 2, 3]
y = x
x += [4, 5]

print(x)
print(y)

🔹 گزینه‌ها:

🔹A)

[1, 2, 3, 4, 5]
[1, 2, 3]


🔹B)

[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]


🔹C)

Error


🔹D)

[4, 5]
[1, 2, 3]


🐍 @python_rd