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

■ گروه پایتون:
@programmers_py
Download Telegram
🔆 چرا پایتون کندتر از C عه، ولی دنیای AI و Data Science رو فتح کرده؟

🔹همه‌مون شنیدیم که می‌گن «پایتون یک زبان کنده!». خب اگه کنده، چرا OpenAI، Google و Meta پروژه‌های هوش مصنوعی‌شون رو روی پایتون پیاده می‌کنن؟
راز داستان چیه؟

🔹 ۱. کتابخونه‌های C/C++ تحت پوشش:

کتابخونه‌های سنگینی مثل NumPy یا PyTorch روی پایتون اجرا می‌شن، اما هسته اصلیشون با C و C++ نوشته شده! پایتون فقط نقش یک «چسب» خوش‌دست رو بازی می‌کنه.

🔹 ۲. سرعت توسعه > سرعت اجرا:

در دنیای واقعی، زمانی که برنامه نویس صرف کدزدن می‌کنه گرون‌تر از زمان پردازش سروره!

🔹 ۳. GIL (Global Interpreter Lock):

قفلی که جلوی اجرای همزمان واقعی چند ترد (Multi-threading) رو می‌گرفت، حالا در نسخه‌های جدید پایتون (Python 3.13+) داره اختیاری/حذف میشه تا پایتون سریع‌تر از همیشه بشه.

🐍 @python_rd
🔆 افزایش ۱۰ برابری سرعت برنامه‌های پایتون فقط با ۱ خط کد!

🔹 تا حالا شده توی پایتون یک تابع محاسباتی سنگین (مثل فاکتوریل، فیبوناچی یا پردازش داده) داشته باشی که با ورودی‌های تکراری مدام اجرا بشه و سی‌پی‌یو رو درگیر کنه؟

🔹پایتون برای این کار یک ابزار فوق‌العاده توی کتابخونه داخلی functools داره به اسم @cache (یا @lru_cache).

🔹 روش عادی (اجرای مجدد محاسبات تکراری):
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

# برای n = 35 چند ثانیه طول می‌کشه و میلیون‌ها محاسبه تکراری انجام میده!
print(fibonacci(35))


🔹روش هوشمندانه با Cache (ذخیره نتایج قبلی در حافظه):
from functools import cache

@cache
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

# اجرای همون کد در کسری از میلی‌ثانیه (O(n) به جای O(2^n))!
print(fibonacci(35))

🔹 چطور کار می‌کنه؟
وقتی دکوراتور @cache رو بالای تابع می‌ذاری، پایتون ورودی‌ها و خروجی‌های تابع رو یادش می‌مونه. دفعه بعد که همون ورودی داده بشه، به جای محاسبه مجدد، بلافاصله جواب رو از رم برمی‌گردونه!

🐍 @python_rd
❤4🔥1
🔆دام خطرناک لیست پیش‌فرض در تابع

🔹این کد در نگاه اول درست به نظر می‌رسه:

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

🔹اما لیست items فقط یک‌بار ساخته می‌شه و بین همه‌ی فراخوانی‌ها مشترکه!

راه درست:

def add_item(item, items=None):
if items is None:
items = []

items

🐍 @python_rd
👍2👎1
🔆 یک خط کد که جلوی باگ‌های عجیب رو می‌گیره!

🔹 به‌جای این‌که فایل رو دستی باز و بسته کنی، از with استفاده کن:
with open("data.txt", "r", encoding="utf-8") as file:
content = file.read()

🔹 حتی اگه وسط کار خطا رخ بده، پایتون فایل رو درست می‌بنده.

کد تمیزتر، مدیریت منابع بهتر، باگ کمتر.

🐍 @python_rd
🔆این ۳ تا سایت بصورت تقلب‌طور نکات کلی در مورد format string توی پایتون رو خلاصه کردن و با مثال توضیح دادن

🔹https://strftime.org/
🔹https://pyformat.info/
🔹https://www.strfti.me/

🐍 @python_rd
🔆کتاب خوبی برای یادگیری مفاهیم یادگیری عمیق به همراه notebook های پایتون که مربوط به کدهای داخل کتابه.

🔹https://udlbook.github.io/udlbook

🐍 @python_rd
🔆لیستی از سوالات مرتبط با سیستم type annotation در زبان پایتون که احتمالا قبلا بهشون برخورد نکرده بودید.

🔹https://python-type-challenges.zeabur.app

🐍 @python_rd
🔆 پیاده‌سازی پایتونی پروژه‌های کتاب معروف "the big book of small python projects"

🔹https://github.com/nihathalici/The-Big-Book-of-Small-Python-Projects

🐍 @python_rd
🙏1
🔆 ترفند: کد تمیزتر و سریع‌تر با dict.get() به جای if-else


🔹 خیلی از برنامه‌نویس‌ها موقع گرفتن مقدار از یک دیکشنری، اول بررسی می‌کنن ببینن کلید وجود داره یا نه. این کار کد رو طولانی و شلوغ می‌کنه.


🔹 روش معمولی و شلوغ:
user_data = {"name": "Reza", "role": "Developer"}

if "age" in user_data:
age = user_data["age"]
else:
age = 18 # مقدار پیش‌فرض

print(age)

🔹 روش حرفه‌ای:
user_data = {"name": "Reza", "role": "Developer"}

# اگر کلید نباشه، خودکار مقدار پیش‌فرض رو برمی‌گردونه
age = user_data.get("age", 18)

print(age)

🔹 چرا این روش بهتره؟

* کد کوتاه‌تر: ۴ خط کد تبدیل به ۱ خط میشه.
* جلوگیری از KeyError: اگر کلید وجود نداشته باشه، برنامه‌ت کرش نمیکنه.
* خوانایی بالا: کدت خواناتر و حرفه‌ای‌تر به‌نظر می‌رسه.

🔹 نکته: اگر مقدار دوم متد .get() رو مشخص نکنی، به صورت پیش‌فرض None برمی‌گردونه.

🐍 @python_rd
🔆 متد init واقعاً Constructor نیست! (داستان واقعی ساخت Object در پایتون)

🔹 خیلی‌ها فکر می‌کنند init شیء جدید را می‌سازد، اما در واقع این متد فقط شیء ساخته‌شده را مقداردهی اولیه (Initialize) می‌کند. سازندهٔ واقعی پایتون متد new است!

🔹 تفاوت اصلی در چیست؟

new:
یک classmethod است که خودِ متغیر cls را می‌گیرد، شیء جدید را ایجاد می‌کند و برمی‌گرداند.
init:
شیء ایجادشده (self) را می‌گیرد و ویژگی‌های آن را تنظیم می‌کند.


🔹 نمونه کاربرد واقعی: پیاده‌سازی الگوی Singleton

اگر بخواهی کلاس فقط و فقط یک نمونه (Instance) در کل برنامه داشته باشد، باید سراغ new بروی:
class DatabaseConnection:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            # ساخت شیء فقط برای بار اول
            cls._instance = super().__new__(cls)
        return cls._instance

# تست:
db1 = DatabaseConnection()
db2 = DatabaseConnection()

print(db1 is db2)  # Output: True (هر دو دقیقاً یک Object هستند)

🔹کاربرد دیگر: تغییر رفتار Typeهای Immutable (مثل تغییر دادن رفتار string یا tuple موقع ساخته شدن).

🐍 @python_rd
❤1
🔆 این سایت مسیرهای یادگیری گام به گام رو در اختیار شما قرار می ده که می تونید برای یادگیری حالت‌های مختلف concurrency در پایتون ازشون استفاده کنید.

🔹https://superfastpython.com/learning-paths

🐍 @python_rd
❤‍🔥1❤1
🔆 مدیریت منابع مثل حرفه‌ای‌ها: چطور با with مدیریت خطای تمیز بنویسیم؟

🔹دستور with رو همه برای باز کردن فایل (open) می‌شناسند، اما قدرتش خیلی بیشتر از این حرف‌هاست. هر جایی که نیاز به الگوی "آماده‌سازی -> اجرا -> تمیزکاری" داری، Context Manager نجات‌دهنده است.

🔹دو روش ساخت Context Manager سفارشی:

.روش اول: استفاده از Magic Methodها

با تعریف متدهای enter و exit در کلاس:
import time

class Timer:
def __enter__(self):
self.start = time.perf_counter()
return self

def __exit__(self, exc_type, exc_val, exc_tb):
self.end = time.perf_counter()
print(f"زمان اجرا: {self.end - self.start:.4f} ثانیه")
# اگر True برگردانی، خطاهای داخل بلوک with سائلنت می‌شوند!
return False

with Timer():
# کدی که می‌خواهی زمان اجرای آن سنجیده شود
sum(i**2 for i in range(1_000_000))

🔹روش دوم: راهکار سریع‌تر با contextlib

بدون نیاز به نوشتن کلاس و فقط با یک Generator:
from contextlib import contextmanager

@contextmanager
def managed_resource():
print("۱. تخصیص منبع (Connect / Open)")
try:
yield "Resource Object"
finally:
print("۲. آزادسازی منبع (Disconnect / Close)")

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

🔹 به چه دردی میخوره؟

مدیریت Transactionهای دیتابیس، قفل‌های Multithreading، و اندازه‌گیری زمان اجرای سرویس‌ها.

🐍 @python_rd
❤1
🔆سایت منابع و نکاتی برای بهتر ساختن اپلیکیشن‌های با کیفیت بالا که البته بیشتر در مورد پایتون و جنگو و فلسک مطلب داره.

🔹https://testdriven.io

🐍 @python_rd
🔆 تا حالا دیدی توی پایتون از علامت @ بین دو تا متغیر استفاده بشه؟!

🔹وقتی صحبت از @ توی پایتون می‌شه، ۹۹٪ افراد یاد Decorator ها می‌افتن. اما پایتون ۳.۵ به بعد، یک عملگر اختصاصی برای ضرب ماتریس‌ها اضافه کرد که دقیقاً همین شکله‌

🔹داستان چیه؟

توی ریاضیات و یادگیری ماشین، ضرب معمولی (درایه‌به‌درایه) با ضرب ماتریسی فرق داره.

* 👈 ضرب درایه‌ای (Element-wise)
@ 👈 ضرب ماتریسی (Matrix Multiplication)

🔹 کد نمونه با کتابخانه NumPy:
import numpy as np

A = np.array([[1, 2],
[3, 4]])

B = np.array([[5, 6],
[7, 8]])

# ضرب درایه‌ای (معمولی)
print(A * B)
# [[ 5 12]
# [21 32]]

# ضرب ماتریسی با عملگر @
print(A @ B)
# [[19 22]
# [43 50]]

🔹 نکته: خودت هم می‌تونی پیاده‌سازیش کنی!

پایتون برای این عملگر یک متد جادویی (Magic Method) به اسم matmul داره. یعنی می‌تونی توی کلاس‌های شخصی خودت هم تعریفش کنی:
class Matrix:
def __init__(self, data):
self.data = data

def __matmul__(self, other):
# اینجا منطق ضرب ماتریس رو می‌نویسی
print("ضرب ماتریسی اجرا شد!")

m1 = Matrix([1, 2])
m2 = Matrix([3, 4])

m1 @ m2 # خروجی: ضرب ماتریسی اجرا شد!

🐍 @python_rd
❤1
🔆با گذاشتن وقت کمی توی ۳۰ روز به تسلط نسبی در زبان پایتون برسید (البته میشه سرعت رو کندتر کرد و ۱۰۰ روزه اینکارو کرد)

🔹https://github.com/Asabeneh/30-Days-Of-Python

🐍 @python_rd
🔆 یک کامپایلر برای زبان C که با پایتون نوشته شده و برای مقاصد آموزشی و یادگیری نحوه کارکرد کامپایلرها میتونه عالی باشه. به راحتی میتونین دیباگ‌اش کنید با Pycharm و کلی چیز جدید یاد بگیرید.

🔹https://github.com/ShivamSarodia/ShivyC

🐍 @python_rd
🔆 یکی از قدرتمندترین و در عین حال کم‌کاربردترین ابزارهای پایتون، functools.lru_cache هست.

🔹این دکوراتور مثل یک سیستم کشینگ (Caching) درون‌برنامه‌ای عمل می‌کنه و نتایج توابع سنگین یا محاسباتی رو ذخیره می‌کنه تا توی اجراهای بعدی با همون ورودی، بدون محاسبات مجدد و در صدم‌ثانیه نتیجه رو برگردونه!


🔹 بدون کشینگ (کند و اجرای مجدد محاسبات):
import time

def get_user_data(user_id):
# فرض کنید این تابع به دیتابیس وصل میشه و ۲ ثانیه طول می‌کشه
time.sleep(2)
return f"User Data for ID: {user_id}"

# هر بار فراخوانی ۲ ثانیه زمان می‌بره
print(get_user_data(101)) # 2 seconds
print(get_user_data(101)) # 2 seconds (دوباره همان زمان!)

🔹 با lru_cache (بهینه‌سازی فوق‌العاده با اضافه کردن ۱ خط):
from functools import lru_cache
import time

@lru_cache(maxsize=128) # حداکثر ۱۲۸ نتیجه اخیر را کش می‌کند
def get_user_data(user_id):
time.sleep(2)
return f"User Data for ID: {user_id}"

print(get_user_data(101)) # اجرا میشه (۲ ثانیه)
print(get_user_data(101)) # آنی و بدون معطلی برمی‌گرده! (0.00 seconds)

🔹 نکات کلیدی:

. پارامتر maxsize: ظرفیت کش را مشخص می‌کند (None یعنی بدون محدودیت).

. شرط مهم: آرگومان‌های تابعی که دکوراتور @lru_cache می‌گیرد باید Hashable باشند (مثل string, int, tuple) نه لیست یا دیکشنری.

. کاربرد: فراخوانی‌های مکرر API، محاسبات سنگین ریاضی، یا کوئری‌های ثابت دیتابیس.


🔹 بونس: اگر خواستید کش را به صورت دستی خالی کنید:
get_user_data.cache_clear()

🐍 @python_rd
❤1
🔆 تا حالا شده یک تابع داشته باشی که مجبور باشه چند نوع ورودی مختلف رو پردازش کنه؟

🔹مثلاً برای پردازش لاگ‌های یک سیستم، ورودی ممکنه یک متن ساده، یک لیست از خطاها یا یک دیکشنری شامل اطلاعات کامل لاگ باشه.

🔹روش معمولی احتمالاً این شکلیه:

def process_log(data):
if isinstance(data, str):
print(f"Text log: {data.upper()}")

elif isinstance(data, list):
print(f"{len(data)} errors found")

elif isinstance(data, dict):
print(f"Log source: {data.get('source')}")

else:
print("Unknown data type")

🔹این کد فعلاً کار می‌کنه، اما هر بار که بخوای نوع جدیدی اضافه کنی، باید همین تابع رو تغییر بدی.

🔹اینجاست که singledispatch وارد میشه.

from functools import singledispatch


@singledispatch
def process_log(data):
print(f"نوع داده پشتیبانی نمی‌شود: {type(data).__name__}")


@process_log.register
def _(data: str):
print(f"لاگ متنی: {data.upper()}")


@process_log.register
def _(data: list):
print(f"تعداد خطاها: {len(data)}")


@process_log.register
def _(data: dict):
print(f"منبع لاگ:گ متنی: SERVER IS DOWN

process_log(["404 is down")
# لاگ متنی: SERVER IS DOWN

process_log(["404", "Timeout", "Database Error"])
# تعداد خطاها: 3

process_log({"source": "AuthService"})
# منبع لاگ: AuthService

🔹تابع اصلی فقط برای حالت پیش‌فرض استفاده میشه و هر نوع داده، پردازش مخصوص خودش رو داره.

🔹مزیتش اینه که به‌جای ساختن یک تابع بزرگ پر از if/elif، منطق هر نوع ورودی رو جدا می‌نویسی.

🔹البته یک نکته مهم وجود داره: singledispatch فقط بر اساس نوع اولین آرگومان تصمیم می‌گیره، نه بر اساس مقدار یا تعداد آرگومان‌ها.

🐍 @python_rd
🔆مجموعه‌ای از بهترین کتابخانه‌های یادگیری ماشین برای زبان پایتون که هر هفته آپدیت میشه

🔹https://github.com/ml-tooling/best-of-ml-python

🐍 @python_rd
🔆 یکی از خطاهای رایج پایتون اینه:

user = User.objects.filter(username="ali").first()

print(user.email)

🔹اگر کاربری با نام ali وجود نداشته باشه، مقدار user برابر با None میشه و این خطا رو می‌گیریم:

AttributeError: 'NoneType' object has no attribute 'email'

🔹راه ساده اینه که قبل از استفاده، وجود کاربر رو بررسی کنیم:

user = User.objects.filter(username="ali").first()

if user is None:
print("کاربر پیدا نشد")
else:
print(user.email)

🔹اگر فقط می‌خوای یک کاربر مشخص رو پیدا کنی، می‌تونی از get_object_or_404 استفاده کنی:

from django.shortcuts import get_object_or_404

user = get_object_or_404(User, username="ali")
print(user.email)

🔹در این حالت اگر کاربر پیدا نشه، جنگو به‌جای خطای نامفهوم NoneType، پاسخ 404 برمی‌گردونه.

🔹نکته مهم اینه که متد first() هیچ‌وقت خطا نمی‌ده؛ اگر چیزی پیدا نکنه، None برمی‌گردونه. پس هرجا از first() استفاده کردی، حواست به مقدار برگشتی باشه.

🐍 @python_rd
❤1