Python Hints
8.63K subscribers
170 photos
11 videos
9 files
141 links
Python tips and tricks
The Good, Bad and the Ugly

توی این کانال فقط قرار هست در مورد core python صحبت کنیم.

این کانال یک بلاگ شخصی هست و پیرامون نظرات و چیزهایی که توی بیش از ۱۰ سال کد زدن یاد گرفتم (فقط برای کمک به دوستان تازه‌کار)

Admin: @Abbasi_ai
Download Telegram
Python Hints
قبلا راجب cache نوشتن برای پروژه‌هایی با محاسبات سنگین صحبت کردم البته توی یک کانال دیگه : https://t.iss.one/pytens/1018 دوستانی که کد تصویر رو متوجه نشدند شاید بهتره اون پیام‌هارو هم بخونند. اینجا میخوام راجب دلیلی صحبت کنم که شما توی مصاحبه midlevel قبول میشی…
در ابتدا
@lru_cache

توی سورس کد از dict استفاده می‌کنه پس ازین نظر فرقی با
cache = {}

نداره اما چرا پس
@lru_cache
تعریف شده ؟
maxsize
بهترین دلیلش هست اگر تعریف بشه Ram با نتایج کش شده پر نمیشه

فرض کنید خروجی محاسبات چندین گیگابایت باشه، اگر محدودیت نداشته باشه مثل
cache = {}

رم رو پر می‌کنه و کد رو از کار میندازه، ولی این اتفاق توی lru_cache نمی‌افته
👍1611
Python Hints
قبلا راجب cache نوشتن برای پروژه‌هایی با محاسبات سنگین صحبت کردم البته توی یک کانال دیگه : https://t.iss.one/pytens/1018 دوستانی که کد تصویر رو متوجه نشدند شاید بهتره اون پیام‌هارو هم بخونند. اینجا میخوام راجب دلیلی صحبت کنم که شما توی مصاحبه midlevel قبول میشی…
اما بحث اصلاً راجب
@lru_cache, ...
نبود و از فرصت استفاده کردم و توضیح دادم.

اما مسئله بحث چی بود، استفاده از cache فقط برای مصاحبه نیست
crawler
موقعیت خیلی مناسبی هست، دوستان زیادی در جریان برخی از کرالر‌های نوشته شده بنده هستند بخصوص مواردی که نیاز به محاسبات پردازشی و درخواست به لینک‌های تو در تو داره

درصد زیادی که کرالرهای بنده بلاک نمیشه یا توی معروفترین موارد تا بیش از ۱۰۰ گیگ دیتای سایت‌های داخلی رو کرال کردم

استفاده از cache هست، یا حتی بهتر استفاده از ابزارهای دیگه که url های کرال شده دوباره براشون درخواست فرستاده نشه.

نکته دیگه راجب
@lru_cache
که فراموش کردم بگم اگر argument های تابع رو جابجا بفرستید، دوباره محاسبات رو انجام میده پس به این نکته توجه کنید ینی :
add(a=1, b=2)
و
add(b=2, a=1)
۲ بار محاسبه میشه
👍2051
__slots__
ازون مواردی هست که ممکنه ۲۰ سال توسعه دهنده پایتون باشید و هیچوقت استفاده نکنید ولی اگر توی شرایط درست و بجا استفاده کنید
قطعا از کابوس نجاتتون میده

توضیحات پست بعدی

@PyHints
👍112🦄2
Python Hints
__slots__ ازون مواردی هست که ممکنه ۲۰ سال توسعه دهنده پایتون باشید و هیچوقت استفاده نکنید ولی اگر توی شرایط درست و بجا استفاده کنید قطعا از کابوس نجاتتون میده توضیحات پست بعدی @PyHints
اول از بزرگترین عیب استفاده از
__slots__
بگم؛ و اونم از دست رفتن
monkey patching
هست؛ خط ۲۱ کد رو نگاه کنید توی حالت معمول اگر یک instance از کلاسی بدون
__slots__
داشتیم هیچوقت به ارور نمیخورد و education تبدیل میشد به یک
instance attribute
و روی p می‌نشست.

همین رفتار اولین کاری که __slots__ می‌کنه رو لو میده حذف __dict__ از کلاس علاوه بر اون __weakref__ رو هم بیخیال میشه
پس مزیت‌هاش بدست میاد :
۱- سرعت بالاتری داره (توی پایتون ۳.۵ تا ۳۰٪ سریعتر میکرد دسترسی به attribute هارو)
۲- حافظه خیلی کمتری استفاده می‌کنه
چون شما دقیقا بهش میگید چه attribute هایی دارید و دیگه dynamic نیستید؛ سربار دیکشنری توی پایتون بسیار زیاد هست.

حالا کجاها استفاده میشه ؟
چندتا مورد من بیشتر از همه دیدم :
مواقعی که از کلاسی که نوشتید ممکنه هزاران یا بیشتر instance ساخته بشه و نیازی هم به monkey patch ندارید (بازی‌های آنلاین - اکانت‌های آنلاین و ...)
حالت دوم :
ABC class

اما اگر توی این ۲ حالت نیستید و محدودیت حافظه براتون پیش نمیاد نباید رفت سراغش
👍2232🔥2
بنظر شما توی این کد خروجی خط ۲۱ چی هست ؟
آیا می‌تونید راجب این رفتار توضیح هم بدید ؟

بحثی داشتم با یکی از دوستان راجب این مطلب که یاد مصاحبه مرحله دوم برای آمازون افتادم موضوع مربوط می‌شه به ۳-۴ سال پیش.
سطح
upper mid-level, senior python
👍9👨‍💻5
Python Hints
بنظر شما توی این کد خروجی خط ۲۱ چی هست ؟ آیا می‌تونید راجب این رفتار توضیح هم بدید ؟ بحثی داشتم با یکی از دوستان راجب این مطلب که یاد مصاحبه مرحله دوم برای آمازون افتادم موضوع مربوط می‌شه به ۳-۴ سال پیش. سطح upper mid-level, senior python
همونطوری که احتمالا حدس زدید؛ خروجی خط ۲۱ :
@PyHints
هست.

اما توضیحاتش مهمتر از اینه که بگید خروجی چی هست :
توی پایتون یک موضوعی داریم به اسم
variable shadowing
اتفاقی که میوفته اینه که توی کد بالا به این موضوعی احترامی گذاشته نمی‌شه اگر name توی کد بالا یک property نبود قطعا متنی که توی خط ۱۹ بهش داده بودیم رو چاپ می‌کرد؛
حالا چرا property باعث شده که به variable shadowing احترام گذاشته نشه

توی پایتون یک موضوع دیگری هم وجود داره به اسم
Descriptor
که خودش ۲ مدل داره و توی کد بالا ما از data descriptor داریم استفاده می‌کنیم وقتی شما از property استفاده می‌کنید چه به صورت تابع چه بصورت decorator اون property در نهایت به صورت data descriptor تعریف میشه
پروتوکل data descriptor به این صورت تعریف میشه:
کلاسی در پایتون که شامل dunder method های :
__get__ and __set__ or __delete__
باشه که توی property هر ۳ مورد وجود داره

پایتون هم که باشعور وقتی متوجه میشه از پروتوکل data descriptor استفاده شده دیگه از __dict__ موجود برای instance اطلاعات نمی‌گیره بلکه
__get__
اون data descriptor رو صدا میزنه به همین دلیل هم خروجی کد بالا

@PyHints
هست.
👍18🤓4
نمونه ای از کاربردهای ۲ تا پست آخر :
__slots__, descriptors

سورس کد مربوط به
dataclasses

@PyHints
👌11👍3
این یکی ساده هست ولی خیلی مهم :

from functools import partial

اگر قرار هست تابعی از فریمورک مورد نظرتون رو همیشه با چندتا
argument
ثابت صدا بزنید حتما از partial استفاده کنید.

هم تمیزتر هست هم کد رو خواناتر می‌کنه
Don't Repeat Yourself
هم که رعایت میشه اگر قرار باشه اون تابع رو بسیار استفاده کنید؛ دیگه لازم نیست آرگومان‌های ثابت رو هی براش ارسال کنید

@PyHints
👍30🔥5👏1
بحث راجب functools, partial کامل نمی‌شه مگر با صحبت راجب
singledispatch

ی decorator خیلی عالی و قوی بجای if-else های تو در تو برای چک کردن type داده

هدف اصلی :
Clean code

فقط نکته مهم این هست که singledispatch با آرگومان اول ورودی تابع کار می‌کنه فقط

پ.ن : توی مثال بالا مثلا اگر خواستید ی تابع برای
int, float
اضافه کنید که هر ۲ رو پشتیبانی کنه در این حالت نیاز دارید از Union و Typing هم استفاده کنید:

from typing import Union

@PyHints
👍19❤‍🔥2
تا داریم از functools صحبت می‌کنیم بیاید و اجازه بدید راجب total_ordering هم صحبت کنیم :

کارش اینه من یک کلاس کاستوم میسازم و میخوام بین آبجکت های کلاسم مقایسه رو پشتیبانی کنم
اما ازونجایی که حال ندارم همه‌ی موارد مقایسه رو بنویسم :
__lt__, __le__, __gt__, __ge__, ....

میام یکی ازین موارد رو پیاده سازی میکنم و در کنارش هم __eq__ رو پیاده سازی میکنم.
توصیه مهمی هست که حتما __eq__ پیاده‌سازی بشه وگرنه باگ مخفی میخورید

باقی عملگرها به لطف
@total_ordering

بصورت خودکار برای کلاس مدنظرم پیاده‌ سازی میشه

@PyHints
👍20❤‍🔥3
Python Hints
تا داریم از functools صحبت می‌کنیم بیاید و اجازه بدید راجب total_ordering هم صحبت کنیم : کارش اینه من یک کلاس کاستوم میسازم و میخوام بین آبجکت های کلاسم مقایسه رو پشتیبانی کنم اما ازونجایی که حال ندارم همه‌ی موارد مقایسه رو بنویسم : __lt__, __le__, __gt__…
اما توی این کد یک مورد bad practice خفن هم وجود داره :

پایتون بصورت خودکار کلاس و object اش روی برای ما hashable می‌کنه
راهکارش هم خیلی ساده‌اس فقط میاد آدرس حافظه اون instance ایی که از کلاس ساختیم رو میگیره و hash میکنه و بهمون بر میگردونه

اما این موضوع تا وقتی کار می‌کنه که :
__eq__()
پیاده سازی نشده باشه اضافه کنم __eq__ برای == استفاده میشه

توی کد بالا وقتی من اومدم و __eq__ رو پیاده سازی کردم باید __hash__ رو هم پیاده سازی کنم بعنوان مثال :

def __hash__(self):
return hash((self.name, self.grade))

حالا اگر به عمد نخواستیم instance هامون hashable باشه چی ؟
برای درک بهتر کد بهترین حالت این هست که از خط زیر استفاده کنید داخل کلاس :
__hash__ = None

اینجوری یوزر یا هرکسی دیگه که کدهای شمارو بخونه درک میکنه که شما به عمد و بنا به دلایل طراحی instance های این کلاس رو hashable نکردید

و فکر نمی‌کنه شما فراموش کردید.

در نهایت به خط 10 هم توجه کنید؛ hardcode نکردم اسم کلاس رو بلکه از
isinstance(other, type(self))

که راجب اهمیتش توی پست‌های قبلی و صحبت راجب __repr__ گفتم.


@PyHints
👍17
جواب برای دوستانی که میگن یوتیوب ویدئو بذار خوندن و یادگیری با متن سخت‌ هست.
با اینترنت ۵۰ مگ
git push
با ۳۷ کیلوبایت آپلود می‌شه
ویدئو چی بذارم 😅😅😅
😁23💔8😭6🐳4
نحوه تعریف decorator می‌تونه نشون بده دولوپر پروژه junior هست یا نه

اگر توی یک پروژه حرفه‌ای مثل کد بالا decorator تعریف می‌کنید و بیش از ۳-۴ بار ازش استفاده میشه شما سیگنال junior developer بودن میدی به کسی که کد رو میخونه.

همیشه گفتم بازم میگم :
اگر میخوای از یک دولوپر انتقام بگیری یا بیچاره‌اش کنی فقط ی decorator اینطوری بنویس و توی کل پروژه استفاده کن

مشکل کد چیه :
همه‌ی متا دیتا مربوط به تابعی که decorate شده مثل func1, func2 رو پاک می‌کنه و اطلاعات decorator رو جاش مینوسته توی حالت معمول این اشتباه نیست و منطق درستی هست
ولی برای decorator خیلی اشتباه داری میزنی.

دیباگ کردن همچین کدی آدم رو دیوونه می‌کنه خروجی رو ببینید name, docstring تابع به wrapper تغییر کرده

راه حل : پست بعدی

@PyHints
👍202🌚1
Python Hints
نحوه تعریف decorator می‌تونه نشون بده دولوپر پروژه junior هست یا نه اگر توی یک پروژه حرفه‌ای مثل کد بالا decorator تعریف می‌کنید و بیش از ۳-۴ بار ازش استفاده میشه شما سیگنال junior developer بودن میدی به کسی که کد رو میخونه. همیشه گفتم بازم میگم : اگر…
راه حل : functools مقدس؛ این آخرین پست درباره functools هست همه موارد مهم این ماژول صحبت شد

from functools import wraps

به لطف دکوریتور wraps به پایتون میگیم که meta data مربوط به تابع اصلی رو نگه داره و اطلاعات تابع wrapper رو روی اون بازنویسی نکنه

خروجی رو اگر دقت کنید docstrign, name تابع به درستی نشون داده شده و debug , .... برای دولوپر بعدی قطعا به مراتب راحت تر خواهد بود.

این ۲ خط تغییر (خط ۱ و ۵) خیلی زندگی‌ها نجات داده و آدمای بزرگی بعد از دیدن این ۲ خط توی کد امید به زندگیشون بالا رفته و دست از خودکشی کشیدن

اگر decorator نوشتی تورو خدا این ۲ خط رو اضافه کن (شاید ۱ زندگی رو نجات دادی)


@PyHints
👌21👍5111
#خارج_از_بحث

این یکی مخصوص دوستان خارج نشین هست.

دیروز تمام روز درگیر مصاحبه و negotiate و مبلغ دستمزد و ... بودم با چندتا شرکت خارج از ایران که قبلا هم با ۲ موردشون پروژه داشتم؛

تقریبا عصر یک صحبتی شد با دوستان که چطوری قیمت دهی و ... انجام میدم
یک سری از موارد که خب شخصی هست ؛ بر اساس گذشته و ... هیچوقت از یک مبلغ خاص کمتر کار نمی‌کنم

ولی وقتی برای مدت طولانی از بازار مصاحبه و .... دور هستم به کمک این سایت حدود دستمزد رو پیدا می‌کنم (برای پیدا کردن کار هم سایت خوبی هست)


https://www.levels.fyi/

بوکمارک کنید و همیشه داشته باشیدش.

@PyHints
👍13😁1
Python Hints
#خارج_از_بحث این یکی مخصوص دوستان خارج نشین هست. دیروز تمام روز درگیر مصاحبه و negotiate و مبلغ دستمزد و ... بودم با چندتا شرکت خارج از ایران که قبلا هم با ۲ موردشون پروژه داشتم؛ تقریبا عصر یک صحبتی شد با دوستان که چطوری قیمت دهی و ... انجام میدم یک سری…
بعنوان مثال یکی از شرکت‌هایی که باهاشون صحبت کردم بکند دولوپر میخواست
mid-level or senior
و توی هلند هم هست شرکت.
این میانگین دستمزد یک
mid-level
توی هلند هست؛ و سنیور تا ۲۰۰ هزار دلار میره

شرکت با من برای relocate هم صحبت کرد؛ اگر هزینه‌های relocate رو کامل بخواد همون اول پرداخت کنه

من باید دستمزدم رو از ۲۰۰ هزارتا کمتر کنم
اگر هزینه‌ای پرداخت نکنه و از من بخواد خودم جابجا بشم دستمزدم از ۲۰۰ هزارتا بیشتر می‌شه و ...

دقت کنید این دستمزدهارو افرادی که با این شرکت‌ها کار کردند یا می‌کنند و حقوق میگیرند زدن پس درست هست تقریبا

این بخش سایت کاملا رایگان هست فقط کافیه شما بگید کجا کار می‌کنید (کشور - شرکت) ؛ چندسال تجربه دارید ؛ مدل همکاری و حقوق دریافتی شما چقدر هست

تا این بخش از سایت بطور کامل برای شما باز بشه.

@PyHints
🙏16👍3
این نمودار رشد کانال هست توی کمتر از ۱ ماه از شروع فعالیت چندتا تشکر لازم داره بنظرم :

۱- اول از همه مرسی از شمایی که می‌خونید و پیشرفت می‌کنید و عزیزانی که فیدبک می‌دهند راجب پست‌ها خیلی کمک کننده هست قطعاً

۲- دمتون گرم که share می‌کنید مطالب رو

۳- حتی اگر کپی هم می‌کنی بازم دستتون درد نکنه که کمک می‌کنید جامعه پایتون رشد کنه

شخصاً هدفی جز رشد برنامه‌نویسی و برنامه‌نویس‌های پایتون تو ایران ندارم، حتی اگر مطالب رو کپی هم کنید بازم قدردان هستم

مرسی از همه ♥️
64👍8❤‍🔥5🫡3
این کد ی مشکل اساسی داره (بزرگ و اساسی) مخصوصا توی پروژه‌های حرفه‌ای
موضوع پیچیده‌ای نیست ولی چون زیاد دیدم ترجیح دادم بهش اشاره کنم تا کم کم دیگه نبینیم.

می‌تونید حدس بزنید چی هست ؟

توضیحات پست بعدی

پ.ن : typing توی پروژه‌ها موضوع مهمی هست اما توی پایتون الزامی نیست
هیچوقت باگ محسوب نمی‌شه و فقط جزو شرایط
clean code
هست (به این مورد اشاره نکنید)

@PyHints
👨‍💻8👌4
Python Hints
این کد ی مشکل اساسی داره (بزرگ و اساسی) مخصوصا توی پروژه‌های حرفه‌ای موضوع پیچیده‌ای نیست ولی چون زیاد دیدم ترجیح دادم بهش اشاره کنم تا کم کم دیگه نبینیم. می‌تونید حدس بزنید چی هست ؟ توضیحات پست بعدی پ.ن : typing توی پروژه‌ها موضوع مهمی هست اما توی پایتون…
مشکل اصلی استفاده از
except Exception as ex:
که دوستان توی کامنت اشاره کردند.

اصطلاحا به این روش میگن
Broader Approach

مسئله اینه که توی کد بالا من با ارور هیچ‌کاری نمیکنم (اما توی این شرایط هم broader approach اشتباه هست) ولی فرض کنید شما باید این موارد رو لاگ بندازید. در این شرایط exception handle شما به درد نمیخوره احتمالا لاگ هم همینطور چون کسی اروری نمی‌بینه که بخواد لاگ فایل رو بخونه (حتی اگر توی لاگ جزئیات بیشتری هم نوشته شده باشه)
منبع بسیاری از BUG های مخفی همین مورد هست.

قبل از اینکه راه حل رو بگم ی موضوع دیگه برای تازه‌کارها اشاره کنم (شوخی و روشی برای ایستگاه کردن junior developer ها بوده البته کمتر دیده می‌شه دیگه ولی ی زمان تو دانشگاها خیلی زیاد بود بخصوص خارج از ایران) شاید بخاطر اینکه دیگه این مدل کد استفاده نمی‌شه

ی مدل دیگه exception داریم که اصطلاحا بهش میگن :
naked exception
از همینجا شاید متوجه شدید دیگه؛ 😂😂

نوع تعریفش اینطوری هست :
except:

قبلا که خیلی مد بود استفاده ازین مورد و هنوز کلمه nude انقدر جاافتاده نبود برای ایستگاه کردن دانشجوهای سال پایینی استفاده میشد (بین‌المللی)
طرف به ارور میخورد بهش میگفتن ؛ naked ات رو بده تا بگم (خیلی وقتا کار به جاهای باریک میرسید مراقب باشید خلاصه 😅😅😅)

ازین ۲ مدل هیچوقت استفاده نکنید که یا BUG مخفی میخورید یا خدایی نکرده ایستگاه می‌شید.

راه حل کد بالا :
۲ تا Exception جدا بنویسید :
except IndexError as ex:
و اگر قرار هست TypeError هم silent کنید در ادامه‌اش
except TypeError as ex:

یا حتی ادغام هر ۲ :
except (IndexError, TypeError) as ex:
👍22❤‍🔥2👌2
Exception Inheritance Hierarchy
اینم موارد اصلی هست که خوبه داشته باشید.

لیست کامل Exception :
https://docs.python.org/3/library/exceptions.html
20👍7
بخاطر صحبت‌هایی که توی گروه (کامنت‌های پست قبلی شد) تصمیم گرفتم راجب مطرح‌ترین حالت های exception handling بطور خلاصه توضیحی بدم :
توی پایتون دوتا استایل کد زدن خیلی معروف وجود داره :
1- easier to ask forgiveness than permission (EAFP)
2- look before you leap (LBYL) A.K.A : ask for permission first

شخصا روش اول رو ترجیح میدم (توی سورس کد پایتون هم دید همین هست اگر خونده باشید بخصوص پایتون ۳.۱۱) داستان روش اول اینه که شما سعی می‌کنه کار رو انجام بدی اگر نشد exception ایی که بر میگرده رو handle می‌کنی و توی اون exception سعی می‌کنی حالت دیگه کار رو انجام بدی و ....

حالت دوم میگه قبل از اینکه ارور بخوری شده ۲۰ تا if, else تو در تو داشته باشی اشکال نداره ولی try - except رو کم کن (خیلی پایتونی نیست این روش)

حالت دوم رو بیشتر توی کدهای جاوا و C++ می‌بینید که صحبت از سربار try-except هست نسبت به if - else (البته شخصا این رو قبول ندارم) این موضوع برای پایتون صادق نیست بخصوص توی پایتون 3.11 و با توجه به معرفی
zero-cost exceptions
البته ۱۰۰٪ هم بدون هزینه نیست (مثل C++ دوست داشتید سرچ کنید راجبش)


اما کدوم استایل رو باید رعایت کنید
LBYL :
داشتن if-else های تو در تو و چک کردن شرایط و جلوگیری از بروز exception یا
EAFP :
داشتن try-except تو در تو (درصورت بروز exception) به هندل کردنش فکر میکنیم اگر exception بوجود نیومد نیازی نداریم شرایط رو بررسی کنیم.

اگر میخواید پایتونی کد بزنید قطعا توی ۹۰٪ شرایط EAFP رو دنبالش باشید؛
اما چطوری ۱۰٪ رو تشخیص بدید ؟

خیلی ساده؛ هر روشی که تعداد خط کد کمتری لازم داشت و تمیزتر بود بعضی وقتا
Ask for permission first (LBYL)
کمک می‌کنه کد خواناتر و تمیزتر باشه.

سعی می‌کنم یک نمونه کد از هر ۲ مورد هم پیدا کنم یا بنویسم و بذارم.

@PyHints
👍282👏1