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

■ گروه پایتون:
@programmers_py
Download Telegram
🔆 یک خط کد که جلوی باگ‌های عجیب رو می‌گیره!

🔹 به‌جای این‌که فایل رو دستی باز و بسته کنی، از 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
🔆 فرمول کثیف اما کاربردی sys._getframe تو پایتون؛ ابزاری که معمولاً تو کدبیس‌های معمولی نمی‌بینی اما برای دیباگ، لاگین پیشرفته و ساخت فریم‌ورک‌ها مثل معجزه عمل می‌کنه.


🔹 چطور بدون پاس دادن اسم تابع، بفهمیم کی کدمون رو صدا زده؟

فرض کن داری یک سیستم لاگین یا دیباگ می‌نویسی و می‌خوای دقیقاً بدونی تابع فعلی از کجا و توسط چه تابعی فراخوانی شده، بدون اینکه مجبور باشی دستی اسم تابع رو ورودی بدی.
import sys


def trace_caller():
# عدد 1 یعنی یک فریم برو عقب‌تر (جایی که این تابع صدا زده شده)
caller_frame = sys._getframe(1)

func_name = caller_frame.f_code.co_name
line_no = caller_frame.f_lineno
file_name = caller_frame.f_code.co_filename

print(f"📍 Called from: {func_name}() at line {line_no} in {file_name}")


def user_login():
# بدون پاس دادن هیچ پامتر اضافی!
trace_caller()


user_login()

🔹 چطوری کار می‌کنه؟

* sys._getframe(0):
فریم حال حاضر (همین جابی که هستیم).

* sys._getframe(1):
فریم فراخوان‌کننده (یک پله عقب‌تر در Stack call).

* f_code.co_name:
اسم تابعی که کد توش اجرا شده.

* f_locals:
حتی می‌تونی به متغیرهای محلیِ تابع فراخوان‌کننده هم دسترسی پیدا کنی!


🔹 نکته امنیتی/معماری:
پیشوند _ نشون می‌ده این یک متد درونی در CPython است. برای منطق اصلی برنامه (Business Logic) ازش استفاده نکن، اما برای دیباگرها، ساخت دکوراتورهای هوشمند و ابزارهای Logging یک سلاح مخفی و فوق‌العاده‌ست!


🐍 @python_rd
❤1
🔆 مفهوم قدرتمند و پنهان init_subclass در پایتون (معرفی‌شده از پایتون ۳.۶)؛ ابزاری شیک و تمیز که جایگزین کدنویسی پیچیده با Metaclassها میشه و بهت اجازه میده رفتار کلاس‌های فرزند (Subclasses) رو کنترل و مدیریت کنی.


🔹 چطور موقع ارث‌بری، کلاس فرزند رو خودکار اعتبارسنجی یا ثبت کنیم؟
فرض کن داری یک فریم‌ورک، Plugin System یا ساختار Modular می‌نویسی و می‌خوای هر وقت کلاسی از کلاس پایه تو ارث‌بری کرد، یک سری قوانین اجرا بشن (مثلاً حتماً یک attribute خاص داشته باشه) یا اسمش تو یک لیست مرکزی ثبت بشه.
قدیم برای این کار از MetaClass استفاده می‌شد، اما الان با init_subclass فوق‌العاده ساده‌تره:

class PluginBase:
# لیستی برای ثبت خودکار تمام پلاگین‌ها
registry = {}

def __init_subclass__(cls, plugin_name=None, **kwargs):
super().__init_subclass__(**kwargs)

# ۱. اجبار فرزند به داشتن ویژگی مشخص
if not hasattr(cls, "author"):
raise TypeError(
f"کلاس {cls.__name__} باید متغیر author داشته باشه!"
)

# ۲. ثبت خودکار کلاس فرزند در سیستم
name = plugin_name or cls.__name__
cls.registry[name] = cls


# --------------------------------------------------
# حالا کلاس‌های فرزند چطور رفتار می‌کنند؟


class PaymentPlugin(PluginBase, plugin_name="zarinpal"):
author = "Amir" # اگر این نبود، پایتون ارور می‌داد!


print(PluginBase.registry)
# خروجی: {'zarinpal': <class '__main__.PaymentPlugin'>}

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

* سادگی فوق‌العاده: نیnewدرگیر شدن با __new__ و مفاهیم سنگین Metaclasses نداری.

* قابلیت پاس دادن آرگومان: می‌تونی موقع ارث‌بری جلوی اسم کلاس والد، ورودی پاس بدی (PluginBase, plugin_name="zarinpal").

* کد تمیزتر (Clean Code): خوانایی برنامه رو برای باقی اعضای تیم چند برابر می‌کنه.


🔹 کاربرد اصلی: ساخت سیستم‌های Plugin، اتوماتیک‌سازی ثبت Modelها (مثل ORMها) و اعمال استانداردهای کدهای سازمانی روی کلاس‌های فرزند.

🐍 @python_rd
🔆اگر با پایتون کار کرده باشید احتمالا zen of python رو شنیدید که چندین جمله است که یه جورایی عصاره فکری پشت طراحی پایتونه. خیلیاش پیچیده‌ان و درکش در لحظه سخته. توی این gist با مثال برای هر کدوم توضیح داده شده.

🔹https://gist.github.com/evandrix/2030615

🐍 @python_rd