PyCoders (پایتون)
Open in Telegram
◇ #پایتون جادوگر دنیای برنامه نویسی! ◇ معرفی حوزه های کاری پایتون ◇ معرفی کتابخونه های کاربردی ◇ معرفی دوره های مفید ◇ معرفی تکنیک ها و نکات ◇ نقشه راه حوزه های مختلف ◇ اخبار و آپدیت های پایتون ◇ و هر چیزی در مورد پایتون! ■ گروه پایتون: @programmers_py
Show more4 105
Subscribers
-124 hours
-17 days
-330 days
Posts Archive
4 106
🔆 نکات کلیدی برای تمیزتر کد زدن در پایتون و چندزبان دیگر
🔹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
4 106
🔆 مجموعهای از نکات و تقلبنامههایی برای زبان برنامهنویسی پایتون
🔹https://gto76.github.io/python-cheatsheet
🐍 @python_rd
4 106
🔆 تکنیک ناشناخته و حرفهای functools.singledispatch (اورلود کردن توابع در پایتون بدون if/elseهای طولانی!)
🔹 چطوری تو پایتون تابع 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_rd4 106
🔆 فایل pip.conf؛ امن کردن Pip جلوی حملات Supply Chain!
🔹 خیلی وقتها توی پروژهها پکیجهای شخصی یا سازمانی نصب میکنیم. حملهای به اسم 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
4 106
🔆 اجرای فرآیند پسزمینه بدون بلاک شدن برنامه با iter() دو آرگومانهای!
🔹 مفهوم: همه با شکل معمولی 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_rd4 106
🔆 چرا نباید از global توی پروژههای پایتونی استفاده کنیم؟
🔹 متغیرهای Global با اینکه کار رو سریع راه میاندازن، اما چالشهای بزرگی ایجاد میکنن:
سخت شدن دیباگ: هر تابعی میتونه متغیر رو تغییر بده و پیدا کردن منشأ ارور سخت میشه.
تستنویسی کابوسوار: تستهای ایزوله (Unit Tests) به مشکل میخورن.
🔹جایگزین: پاس دادن متغیرها به عنوان پارامتر ورودی تابع، یا استفاده از الگوریتمهای Object-Oriented و تزریق وابستگی (Dependency Injection).
🐍 @python_rd
4 106
🔆 جادوی init_subclass: جایگزین مدرن و تمیز برای Metaclassها
🔹 اکثر پایتونکارها برای مانیتور کردن، ثبت (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_rd4 106
🔆 ۱۰۰ تکه کد کاربردی برای حل مسائل روزمره و رایج در برنامهنویسی پایتون
therenegadecoder.com/code/python-code-snippets-for-everyday-problems
🐍 @python_rd
4 106
🔆 پروژههای جالب و راحت برای افراد تازهکار در پایتون
🔹https://hackr.io/blog/python-projects
🐍 @python_rd
4 106
🔆 یه وبسایت خوب برای یادگیری بازیسازی ساده با پایتون و pygame به همراه پروژه های عملی
🔹programarcadegames.com
🐍 @python_rd
4 106
🔆 اشتباه رایج: هندل کردن استثناها بدون ذکر نوع خطا
🔹 نوشتن یک عبارت اگزپت خالی یا گرفتن کلاس کلی اکسپشن یکی از بدترین عادتهای کدنویسیه، چون تمام خطاهای سیستمی مثل بستن برنامه با کنترل سی یا خطاهای نگارشی رو مخفی میکنه.
🔹 کد پر از ریسک خطاهای نامرتبط رو پنهان میکنه، در حالی که راهکار درست اینه که دقیقاً نوع خطایی که انتظار داری رخ بده رو شکار کنی و ثبتش کنی.
# کد پر از باگ و مخفیکننده مشکلات
# try:
# val = int(user_input)
# except:
# pass
# راهکار استاندارد و شفاف
try:
val = int(user_input)
except ValueError as e:
print(f"فرمت ورودی نامعتبر است: {e}")
🔹 با این کار اگر توی تابع باگ عمیقتری مثل خطای دسترسی به حافظه یا نامگذاری اشتباه وجود داشته باشه، لاگ میشه و از دید تیم فنی مخفی نمیمونه.
🐍 @python_rd4 106
🔆 تله کپی سطحی در ساختارهای تودرتو
🔹 خیلی از دولوپرهای پایتون تفاوت بین کپی معمولی و دیپکپی رو نمیدونن و وقتی دیتای یک دیکشنری یا لیست تو در تو رو کپی میکنن، با تغییر مقدار یکی، اون یکی هم ناخواسته تغییر میکنه. خروجی کد زیر رو بررسی کن:
original = [[1, 2], [3, 4]]
shallow_copy = list(original)
shallow_copy[0][0] = 999
print(original[0][0])
🔹 خروجی عدد ۹۹۹ خواهد بود نه عدد ۱! دلیلش اینه که متد کپی سطحی فقط رفرنس لیستهای داخلی رو کپی میکنه. اگر میخوای کپی کاملاً ایزولهای بسازی که با تغییر دادنش آسیبی به اصل داده نرسه، باید از متد دیپکپی در ماژول استاندارد کپی استفاده کنی.
🐍 @python_rd4 106
🌐 ولیدیشن سریع دیتا با پایدنتیک
🔹 بررسی دستی دیکشنریها برای اطمینان از اینکه سن کاربر عدده یا ایمیلش فرمت درستی داره، کاری تکراری، خستهکننده و مستعد بروز خطاست.
🔹 کتابخانه پایدنتیک بهت اجازه میده با تعریف یک کلاس ساده و استفاده از تایپهینتهای پایتون، ورود هرگونه داده نامعتبر رو به لایههای عمیق برنامه در همان لحظه اول متوقف کنی.
from pydantic import BaseModel, EmailStr
class UserProfile(BaseModel):
name: str
age: int
email: EmailStr
# اعتبارسنجی خودکار و تبدیل تایپها
user = UserProfile(name="علی", age=25, email="ali@example.com")
print(user.model_dump())
🔹 این ابزار هسته اصلی فریمورکهای مدرنی مثل فستایپیآی هست و نوشتن کدهای بکاند رو امن، تمیز و کاملاً تایپسیف میکنه.
🐍 @python_rd4 106
🌐 تکنیک عمیق: ژنراتورها در برابر اشغال حافظه
🔹 اگه توی پایتون بخوای یک فایل چند گیگابایتی لاگ رو بخونی یا روی چند میلیون عدد عملیات انجام بدی، ساختن یک لیست معمولی رم سیستمت رو کامل پر میکنه و سیستم قفل میکنه.
🔹 راهکار پایتونیک استفاده از ژنراتورها به جای لیست کامپرهنشنه. با عوض کردن کروشه به پرانتز معمولی، پایتون به جای ساختن کل دیتا در رم، فرمول تولید اون رو ذخیره میکنه و آیتمها رو تکبهتک تحویلت میده.
# روش سنگین برای رم (میلیونها عدد یکجا ساخته میشن)
# numbers_list = [x * 2 for x in range(10_000_000)]
# روش بهینه با ژنراتور (مصرف رم نزدیک به صفر)
numbers_gen = (x * 2 for x in range(10_000_000))
print(next(numbers_gen))
print(next(numbers_gen))
🔹 این مفهوم دقیقاً تفاوت اصلی دولوپرهای حرفهای رو موقع کار با دادههای سنگین، وب اسکرپینگ یا لاگآنالایزرها رقم میزنه.
🐍 @python_rd4 106
🔆 کد زیر رو با دقت نگاه کن و حدس بزن خروجی نهایی دستور پرینت چی میشه.
data = (1, 2, [30, 40])
try:
data[2] += [50]
except TypeError:
pass
print(data)
1. به نظرت برنامه با ارور متوقف میشه
2. تاپل اصلاً دستنخورده باقی میمونه
3. مقدار ۵۰ به لیست داخل تاپل اضافه میشه
🔹تحلیلت رو توی کامنتها بنویس
🐍 @python_rd4 106
🔆 خیلی وقتا توی پایتون میخوایم یه کاری مثل حذف یک فایل موقت یا پاک کردن یک کلید از دیکشنری رو انجام بدیم و مطمئن نیستیم وجود داره یا نه. راه سنتی اینه که چهار خط try و except بنویسیم و آخرش pass بذاریم که کدمون رو شلوغ و ناخوانا میکنه.
🔹 یک راهکار خیلی تمیزتر استفاده از ماژول بیلتاین contextlib و متد suppress هست. با این قابلیت به جای بلوک تکراری خطا، در یک خط پایتونی و خوانا میگی دقیقاً چه خطایی نادیده گرفته بشه بدون اینکه جریان برنامه به هم بریزه.
import os
from contextlib import suppress
with suppress(FileNotFoundError):
os.remove(".cache_temp.json")
🔹 این روش هم خوانایی کدت رو بالا میبره و هم دقیقاً به بقیه تیم نشون میده که قصدت نادیده گرفتن کنترلشده یک خطای مشخص بوده نه خاموش کردن تمام باگها.
🐍 @python_rd4 106
🔆 ترفند پیشرفته
contextlib و تمیزکاری خودکار
🔹 چطوری با ۶ خط کد، سرعت اجرای توابع رو بدون تغییر دادنشون بسنجیم؟
🔹 بهجای اینکه هر بار قبل و بعد از یک بلاک کد time.time() بنویسید یا برای باز و بسته کردن کانکشنها کلی try/finally کثیف بزنید، با ماژول استاندارد contextlib میتونید کانتکست منیجر اختصاصی خودتون رو مثل آب خوردن با دستور with پیاده کنید!
🔹 نمونه کد عملی:
import time
from contextlib import contextmanager
@contextmanager
def execution_timer(task_name: str):
start = time.perf_counter()
print(f"⏳ شروع عملیات: {task_name}...")
try:
yield # کدهای داخل بلوک with اینجا اجرا میشن
finally:
elapsed = time.perf_counter() - start
print(f"✅ پایان عملیات {task_name} | زمان اجرا: {elapsed:.4f} ثانیه")
# استفاده خیلی شیک و خوانا در هر کجای پروژه:
with execution_timer("پردازش دیتاهای سنگین"):
total = sum(i ** 2 for i in range(2_000_000))
🔹 نتیجه: حتی اگه خطایی وسط کد بیفته، بخش finally اجرا میشه و هیچ ریسورسی (مثل فایل، قفل، یا کانکشن) باز نمیمونه.
🐍 @python_rd4 106
🔆 فهرستی ارزشمند برای برنامهنویسان حرفهای. مناسب برای توسعهدهندگان بکاند، فرانتاند، دواپس و برنامهنویسان عمومی.
🔹https://github.com/charlax/professional-programming
🐍 @python_rd
4 106
🔆 معجزه
Pydantic برای اعتبارسنجی و تبدیل تمیز دادهها
🔹 دیگه با دست دیتای ورودی رو چک نکن! (اعتبارسنجی مدرن در پایتون با Pydantic)
🔹 خیلی وقتا دیتایی از ورودی، کاربر یا API به دستمون میرسه (مثلاً JSON) و کلی خط کد مینویسیم تا چک کنیم سن حتماً عدد باشه، ایمیل فرمت درست داشته باشه و فیلدها خالی نباشن.
🔹 کتابخونه Pydantic این کار رو با تایپ هینتهای خود پایتون فوقالعاده ساده و تمیز کرده:
🔹 نمونه کد عملی:
from datetime import datetime
from pydantic import BaseModel, EmailStr, Field, field_validator
class UserRegisterSchema(BaseModel):
name: str = Field(..., min_length=3, max_length=50)
email: EmailStr
age: int = Field(..., ge=18, le=100) # سن باید بین ۱۸ تا ۱۰۰ باشه
joined_at: datetime = Field(default_factory=datetime.now)
@field_validator("name")
def name_must_not_contain_numbers(cls, value):
if any(char.isdigit() for char in value):
raise ValueError("نام نباید شامل عدد باشد")
return value
# تست با دیتای خام:
raw_data = {
"name": "Ali Dolati",
"email": "ali@example.com",
"age": "25" # خود پایتون استرینگ رو تبدیل به عدد میکنه!
}
try:
user = UserRegisterSchema(**raw_data)
print("دیتای تمیز و معتبر:", user.model_dump())
except Exception as e:
print("خطای ولیدیشن:", e)
🔹 چرا کاربردیه؟ هسته اصلی ابزارهایی مثل FastAPI و لانگچین همین Pydantic هست و تبدیل دادهها (Data Parsing) رو بهشدت امن و سریع میکنه.
🐍 @python_rd