🔆 تله کپی سطحی در ساختارهای تودرتو
🔹 خیلی از دولوپرهای پایتون تفاوت بین کپی معمولی و دیپکپی رو نمیدونن و وقتی دیتای یک دیکشنری یا لیست تو در تو رو کپی میکنن، با تغییر مقدار یکی، اون یکی هم ناخواسته تغییر میکنه. خروجی کد زیر رو بررسی کن:
🔹 خروجی عدد ۹۹۹ خواهد بود نه عدد ۱! دلیلش اینه که متد کپی سطحی فقط رفرنس لیستهای داخلی رو کپی میکنه. اگر میخوای کپی کاملاً ایزولهای بسازی که با تغییر دادنش آسیبی به اصل داده نرسه، باید از متد دیپکپی در ماژول استاندارد کپی استفاده کنی.
🐍 @python_rd
🔹 خیلی از دولوپرهای پایتون تفاوت بین کپی معمولی و دیپکپی رو نمیدونن و وقتی دیتای یک دیکشنری یا لیست تو در تو رو کپی میکنن، با تغییر مقدار یکی، اون یکی هم ناخواسته تغییر میکنه. خروجی کد زیر رو بررسی کن:
original = [[1, 2], [3, 4]]
shallow_copy = list(original)
shallow_copy[0][0] = 999
print(original[0][0])
🔹 خروجی عدد ۹۹۹ خواهد بود نه عدد ۱! دلیلش اینه که متد کپی سطحی فقط رفرنس لیستهای داخلی رو کپی میکنه. اگر میخوای کپی کاملاً ایزولهای بسازی که با تغییر دادنش آسیبی به اصل داده نرسه، باید از متد دیپکپی در ماژول استاندارد کپی استفاده کنی.
🐍 @python_rd
🔆 اشتباه رایج: هندل کردن استثناها بدون ذکر نوع خطا
🔹 نوشتن یک عبارت اگزپت خالی یا گرفتن کلاس کلی اکسپشن یکی از بدترین عادتهای کدنویسیه، چون تمام خطاهای سیستمی مثل بستن برنامه با کنترل سی یا خطاهای نگارشی رو مخفی میکنه.
🔹 کد پر از ریسک خطاهای نامرتبط رو پنهان میکنه، در حالی که راهکار درست اینه که دقیقاً نوع خطایی که انتظار داری رخ بده رو شکار کنی و ثبتش کنی.
🔹 با این کار اگر توی تابع باگ عمیقتری مثل خطای دسترسی به حافظه یا نامگذاری اشتباه وجود داشته باشه، لاگ میشه و از دید تیم فنی مخفی نمیمونه.
🐍 @python_rd
🔹 نوشتن یک عبارت اگزپت خالی یا گرفتن کلاس کلی اکسپشن یکی از بدترین عادتهای کدنویسیه، چون تمام خطاهای سیستمی مثل بستن برنامه با کنترل سی یا خطاهای نگارشی رو مخفی میکنه.
🔹 کد پر از ریسک خطاهای نامرتبط رو پنهان میکنه، در حالی که راهکار درست اینه که دقیقاً نوع خطایی که انتظار داری رخ بده رو شکار کنی و ثبتش کنی.
# کد پر از باگ و مخفیکننده مشکلات
# try:
# val = int(user_input)
# except:
# pass
# راهکار استاندارد و شفاف
try:
val = int(user_input)
except ValueError as e:
print(f"فرمت ورودی نامعتبر است: {e}")
🔹 با این کار اگر توی تابع باگ عمیقتری مثل خطای دسترسی به حافظه یا نامگذاری اشتباه وجود داشته باشه، لاگ میشه و از دید تیم فنی مخفی نمیمونه.
🐍 @python_rd
🔆 یه وبسایت خوب برای یادگیری بازیسازی ساده با پایتون و pygame به همراه پروژه های عملی
🔹programarcadegames.com
🐍 @python_rd
🔹programarcadegames.com
🐍 @python_rd
❤3
🔆 پروژههای جالب و راحت برای افراد تازهکار در پایتون
🔹https://hackr.io/blog/python-projects
🐍 @python_rd
🔹https://hackr.io/blog/python-projects
🐍 @python_rd
Hackr.io
Top 40 Python Projects for Programmers (Beginner to Advanced)
Explore 40+ hands-on Python projects, from beginner-friendly automation to professional portfolio applications, with step-by-step tutorials and video walkthroughs.
🔆 ۱۰۰ تکه کد کاربردی برای حل مسائل روزمره و رایج در برنامهنویسی پایتون
therenegadecoder.com/code/python-code-snippets-for-everyday-problems
🐍 @python_rd
therenegadecoder.com/code/python-code-snippets-for-everyday-problems
🐍 @python_rd
The Renegade Coder
100 Python Code Snippets for Everyday Problems | The Renegade Coder
Everything you regularly Google just found its place in this list. Say hello to a growing list of Python code snippets for everyday problems.
🔆 جادوی init_subclass: جایگزین مدرن و تمیز برای Metaclassها
🔹 اکثر پایتونکارها برای مانیتور کردن، ثبت (Registration) یا ولیدیشن کلاسهای فرزندی که از یک کلاس به ارث میرسن، سراغ Metaclass میرن. اما متانویسی کد رو پیچیده، سنگین و خواناییش رو سخت میکنه.
🔹 از پایتون ۳.۶ به بعد، یک «تاس جادویی» به اسم init_subclass اضافه شد که ۹۰٪ نیازهای شما به متانویسی رو بدون هیچ پیچیدگی برطرف میکنه!
🔹 کاربرد واقعیش کجاست؟ (ساخت یک Plugin System خودکار)
🔹 فرض کنید میخواید هر وقت کلاسی از کلاس پایه شما ارثبری کرد، اسمش تلقائی توی یک دیکشنری ثبت بشه:
🔹به چه دردی میخوره؟
بدون ساخت Metaclass پیچیده، رفتارهای ارثبری رو مدیریت میکنید.
میتونید ورودیهای سفارشی (مثل plugin_name) مستقیماً موقع ارثبری کلاس بهش بدید.
کد کاملاً تمیز، خوانا و مطابق استاندارد روز پایتونه.
🐍 @python_rd
🔹 اکثر پایتونکارها برای مانیتور کردن، ثبت (Registration) یا ولیدیشن کلاسهای فرزندی که از یک کلاس به ارث میرسن، سراغ Metaclass میرن. اما متانویسی کد رو پیچیده، سنگین و خواناییش رو سخت میکنه.
🔹 از پایتون ۳.۶ به بعد، یک «تاس جادویی» به اسم init_subclass اضافه شد که ۹۰٪ نیازهای شما به متانویسی رو بدون هیچ پیچیدگی برطرف میکنه!
🔹 کاربرد واقعیش کجاست؟ (ساخت یک Plugin System خودکار)
🔹 فرض کنید میخواید هر وقت کلاسی از کلاس پایه شما ارثبری کرد، اسمش تلقائی توی یک دیکشنری ثبت بشه:
class BasePlugin:
plugins = {}
def __init_subclass__(cls, plugin_name: str = None, **kwargs):
super().__init_subclass__(**kwargs)
# اگر نام پلاگین مشخص نشده بود، از اسم خود کلاس استفاده کن
name = plugin_name or cls.__name__
cls.plugins[name] = cls
# حالا هر پلاگینی تعریف بشه، اتوماتیک ثبت میشه:
class AudioPlugin(BasePlugin, plugin_name="audio_player"):
pass
class VideoPlugin(BasePlugin, plugin_name="video_player"):
pass
print(BasePlugin.plugins)
# خروجی:
# {'audio_player': <class '__main__.AudioPlugin'>, 'video_player': <class '__main__.VideoPlugin'>}
🔹به چه دردی میخوره؟
بدون ساخت Metaclass پیچیده، رفتارهای ارثبری رو مدیریت میکنید.
میتونید ورودیهای سفارشی (مثل plugin_name) مستقیماً موقع ارثبری کلاس بهش بدید.
کد کاملاً تمیز، خوانا و مطابق استاندارد روز پایتونه.
🐍 @python_rd
👍1
🔆 چرا نباید از global توی پروژههای پایتونی استفاده کنیم؟
🔹 متغیرهای Global با اینکه کار رو سریع راه میاندازن، اما چالشهای بزرگی ایجاد میکنن:
سخت شدن دیباگ: هر تابعی میتونه متغیر رو تغییر بده و پیدا کردن منشأ ارور سخت میشه.
تستنویسی کابوسوار: تستهای ایزوله (Unit Tests) به مشکل میخورن.
🔹جایگزین: پاس دادن متغیرها به عنوان پارامتر ورودی تابع، یا استفاده از الگوریتمهای Object-Oriented و تزریق وابستگی (Dependency Injection).
🐍 @python_rd
🔹 متغیرهای Global با اینکه کار رو سریع راه میاندازن، اما چالشهای بزرگی ایجاد میکنن:
سخت شدن دیباگ: هر تابعی میتونه متغیر رو تغییر بده و پیدا کردن منشأ ارور سخت میشه.
تستنویسی کابوسوار: تستهای ایزوله (Unit Tests) به مشکل میخورن.
🔹جایگزین: پاس دادن متغیرها به عنوان پارامتر ورودی تابع، یا استفاده از الگوریتمهای Object-Oriented و تزریق وابستگی (Dependency Injection).
🐍 @python_rd
❤5👍1
🔆 اجرای فرآیند پسزمینه بدون بلاک شدن برنامه با iter() دو آرگومانهای!
🔹 مفهوم: همه با شکل معمولی iter(iterable) آشنا هستیم. اما کمتر کسی میدونه که iter() یک فرم دو آرگومانهای به شکل iter(callable, sentinel) داره!
🔹 کاربرد واقعی: خواندن فایلهای حجیم یا Stream دیتابیس/شبکه تکهتکه (Chunk) تا زمانی که به یک مقدار خاص (Sentinel) برسی، بدون نیاز به نوشتن حلقه while True و شرطهای اضافه!
🔹 به چه دردی میخوره؟
کد فوقالعاده تمیز، پایتونیک و بدون نیاز به تعریف متغیرهای موقت درون حلقه میشه.
🐍 @python_rd
🔹 مفهوم: همه با شکل معمولی iter(iterable) آشنا هستیم. اما کمتر کسی میدونه که iter() یک فرم دو آرگومانهای به شکل iter(callable, sentinel) داره!
🔹 کاربرد واقعی: خواندن فایلهای حجیم یا Stream دیتابیس/شبکه تکهتکه (Chunk) تا زمانی که به یک مقدار خاص (Sentinel) برسی، بدون نیاز به نوشتن حلقه while True و شرطهای اضافه!
# خواندن یک فایل خطبهخط یا بلوکی تا رسیدن به خط خالی:
with open('data.txt', 'r') as f:
# حلقه تا زمانی ادامه پیدا میکنه که خروجی f.readline برابر '' (خط خالی) بشه
for line in iter(f.readline, ''):
process(line.strip())
🔹 به چه دردی میخوره؟
کد فوقالعاده تمیز، پایتونیک و بدون نیاز به تعریف متغیرهای موقت درون حلقه میشه.
🐍 @python_rd
🔆 فایل pip.conf؛ امن کردن Pip جلوی حملات Supply Chain!
🔹 خیلی وقتها توی پروژهها پکیجهای شخصی یا سازمانی نصب میکنیم. حملهای به اسم Dependency Confusion وجود داره که اگر نام پکیج داخلی شما با یک پکیج عمومی روی PyPI یکی باشه، Pip ممکنه نسخه مخرب عمومی رو دانلود کنه!
🔹 راه حل: ایجاد یک فایل کانفیگ اختصاصی برای Pip تا اولویت دانلود رو فقط روی مخزن امن تنظیم کنه:
🔹 به چه دردی میخوره؟
با اضافه کردن require-hashes = true حتی اگر کسی پکیجی روی PyPI رو هک کنه و تغییر بده، تا زمانی که Hash اون تغییر نکرده باشه Pip اجازه نصب نمیده. این نکته برای کسانی که پروژه واقعی و تجاری میزنن عالیه.
🐍 @python_rd
🔹 خیلی وقتها توی پروژهها پکیجهای شخصی یا سازمانی نصب میکنیم. حملهای به اسم Dependency Confusion وجود داره که اگر نام پکیج داخلی شما با یک پکیج عمومی روی PyPI یکی باشه، Pip ممکنه نسخه مخرب عمومی رو دانلود کنه!
🔹 راه حل: ایجاد یک فایل کانفیگ اختصاصی برای Pip تا اولویت دانلود رو فقط روی مخزن امن تنظیم کنه:
# مسیر فایل: ~/.config/pip/pip.conf
[global]
index-url = https://your-private-repo.com/simple
extra-index-url = https://pypi.org/simple
require-hashes = true
🔹 به چه دردی میخوره؟
با اضافه کردن require-hashes = true حتی اگر کسی پکیجی روی PyPI رو هک کنه و تغییر بده، تا زمانی که Hash اون تغییر نکرده باشه Pip اجازه نصب نمیده. این نکته برای کسانی که پروژه واقعی و تجاری میزنن عالیه.
🐍 @python_rd
🔆 تکنیک ناشناخته و حرفهای functools.singledispatch (اورلود کردن توابع در پایتون بدون if/elseهای طولانی!)
🔹 چطوری تو پایتون تابع Overloading تمیز بنویسیم؟
خیلی وقتها پیش میاد که میخوایم یه تابع بستگی به اینکه چه جنس ورودیای (String, List, Dict...) بهش میدیم، رفتار متفاوتی داشته باشه. روش مبتدیانه چیه؟ نوشتن یه سلسله if isinstance(...) طولانی!
اما روش سینیورها توی پایتون استفاده از singledispatch از کتابخونه استاندارد functools هست.
🔹به چه دردی میخوره؟
کد بسیار کپسوله، خلوت و خوانا میشه.
اصل Open/Closed رعایت میشه (میتونی بعداً بدون دست زدن به تابع اصلی، تایپ جدید اضافه کنی).
🐍 @python_rd
🔹 چطوری تو پایتون تابع Overloading تمیز بنویسیم؟
خیلی وقتها پیش میاد که میخوایم یه تابع بستگی به اینکه چه جنس ورودیای (String, List, Dict...) بهش میدیم، رفتار متفاوتی داشته باشه. روش مبتدیانه چیه؟ نوشتن یه سلسله if isinstance(...) طولانی!
اما روش سینیورها توی پایتون استفاده از singledispatch از کتابخونه استاندارد functools هست.
from functools import singledispatch
@singledispatch
def process_data(data):
raise NotImplementedError("این تایپ پشتیبانی نمیشه!")
@process_data.register(str)
def _(data):
return f"متن پردازش شد: {data.upper()}"
@process_data.register(list)
def _(data):
return f"لیست پردازش شد با طول: {len(data)}"
@process_data.register(dict)
def _(data):
return f"کلیدهای دیکشنری: {list(data.keys())}"
# تست تابع
print(process_data("hello")) # متن پردازش شد: HELLO
print(process_data([1, 2, 3])) # لیست پردازش شد با طول: 3
🔹به چه دردی میخوره؟
کد بسیار کپسوله، خلوت و خوانا میشه.
اصل Open/Closed رعایت میشه (میتونی بعداً بدون دست زدن به تابع اصلی، تایپ جدید اضافه کنی).
🐍 @python_rd
👍2
🔆 مجموعهای از نکات و تقلبنامههایی برای زبان برنامهنویسی پایتون
🔹https://gto76.github.io/python-cheatsheet
🐍 @python_rd
🔹https://gto76.github.io/python-cheatsheet
🐍 @python_rd
gto76.github.io
Comprehensive Python Cheatsheet
Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language.
❤1
🔆 نکات کلیدی برای تمیزتر کد زدن در پایتون و چندزبان دیگر
🔹github.com/zedr/clean-code-python
🔹github.com/jupeter/clean-code-php
🔹github.com/ryanmcdermott/clean-code-javascript
🔹github.com/thangchung/clean-code-dotnet
🔹github.com/labs42io/clean-code-typescript
🐍 @python_rd
🔹github.com/zedr/clean-code-python
🔹github.com/jupeter/clean-code-php
🔹github.com/ryanmcdermott/clean-code-javascript
🔹github.com/thangchung/clean-code-dotnet
🔹github.com/labs42io/clean-code-typescript
🐍 @python_rd
🔆 مدیریت منابع با contextlib
🔹 از تکرار try...finally برای بستن فایلها و اتصالها خسته شدی؟
🔹 پایتون ابزاری به نام Context Manager داره که با دستور with استفاده میشه. اما اگر بخوای خودت یک Context Manager سفارشی بسازی، نیازی نیست حتماً کلاس با متدهای enter و exit بنویسی!
با ماژول contextlib و دکوراتور @contextmanager میتونی خیلی تمیز این کار رو انجام بدی:
🐍 @python_rd
🔹 از تکرار 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
🔆 خروجی این تکه کد چیه؟
🔹گزینهها:
الف) [1], [2], [9, 9, 3], [4]
ب) [1], [1, 2], [9, 9, 3], [1, 2, 4]
ج) [1], [2], [3], [4]
🐍 @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) تولید میکنه:
🔹با این روش میتونی فایلهای چند گیگابایتی رو با مصرف چند مگابایت رم پردازش کنی!
🐍 @python_rd
🔹 وقتی یک تابع لیست بزرگی از دادهها رو با 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 میتوانید این کار را خیلی سریعتر و پایتونیکتر انجام دهید.
🐍 @python_rd
🔹 ساخت 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 /
▪️ تیمهای توسعه کتابخانههای بزرگ مانند NumPy و PyTorch در حال بازنویسی بخشهای C-API خود برای سازگاری با حالت بدون GIL هستند.
▪️ طبق پیشبینی هسته مرکزی، پایتون در پردازشهای سنگین موازی تا چند برابر افزایش کارایی را تجربه خواهد کرد.
🔹 منبع رسمی:
• مستندات رسمی PEP 703: peps.python.org/pep-0703
• اعلامیه Steering Council پایتون: discuss.python.org
🐍 @python_rd
🔹 یک رویداد تاریخی: حذف قفل مفسر (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
Python Enhancement Proposals (PEPs)
PEP 703 – Making the Global Interpreter Lock Optional in CPython | peps.python.org
CPython’s global interpreter lock (“GIL”) prevents multiple threads from executing Python code at the same time. The GIL is an obstacle to using multi-core CPUs from Python efficiently. This PEP proposes adding a build configuration (--disable-gil) to...
🔆 راز مکانیزم پیادهسازی و تغییر جهت
🔹 باگ ریاضیاتی پنهان: چرا پایتون هیچوقت نمیتواند لیستی از NaNها را مرتب کند؟!
🔹 در پایتون، مقدار
nan طبق استاندارد IEEE-754 با خودش هم برابر نیست!
🔹 حالا شگفتی ماجرا در متد
الگوریتم مرتبسازی CPython یعنی Timsort بر اصل تقارن و ترتیبی بودن مقایسهها استوار است. اگر شما لیستی شامل اعداد و NaN را با
🔹 نتیجه خروجی به ترتیب قرارگیری اولیه عناصر بستگی دارد و غیرقابلپیشبینی است!
🔹 پایتون هیچ خطایی (Error) raise نمیکند، اما خروجی نهایی مرتبشده نخواهد بود!
🔹 مهندسان CPython سالهاست که در گیتهاب پایتون روی این موضوع بحث دارند و تصمیم گرفتهاند برای حفظ پرفورمنس Timsort، هیچ لایه اعتبارسنجی اضافی اضافه نکنند و این مسئولیت را روی دوش برنامهنویس بگذارند!
🐍@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
کوییز پایتون
🔆 خروجی اجرای کد زیر چیست؟
🔹 گزینهها:
1️⃣
2️⃣
3️⃣ خطای مدیریتنشده رخ میدهد و برنامه متوقف میشود
4️⃣ خروجی
🐍@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