Python Hints
8.62K 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
بحث راجب 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
توی این مثال (قطعا غیر واقعی)
هر ۲ تا روش رو بررسی کردیم و البته قانون
exception
هم رعایت شده.
تفاوت سرعت رو خودتون می‌بینید دلیلش هم اینه که اسم تابع رو وقتی کاربر می‌بینه توی ۹۹٪ موارد قطعا متوجه هست که ۲ تا عدد باید بده و ...
توی
LBYL
حتی اگر همه چیز درست باشه کد باید شرط‌ها رو چک کنه و این زمان رو کند می‌کنه تا خروجی بده
EAFP
سعی می‌کنه خروجی رو سریعا محاسبه کنه ۱٪ اگر به exception بخوره handler مربوط به اون نوع exception رو اجرا می‌کنه و این یعنی سربار کمتر

تمیزی کد هم که قطعا EAFP بسیار بسیار پایتونی تر هست.

@PyHints
👍262👏1
Python Hints
توی این مثال (قطعا غیر واقعی) هر ۲ تا روش رو بررسی کردیم و البته قانون exception هم رعایت شده. تفاوت سرعت رو خودتون می‌بینید دلیلش هم اینه که اسم تابع رو وقتی کاربر می‌بینه توی ۹۹٪ موارد قطعا متوجه هست که ۲ تا عدد باید بده و ... توی LBYL حتی اگر همه چیز…
راجب کدهم کمی توضیح بدم
return NotImplemented
بیشتر توی کلاس‌ها و متدهای مقایسه‌ای استفاده می‌شه مثلا :
__lt__ , __gt__, ...
به ترتیب برای علامت‌های :
<, >

اینجوری هست که شما میزنید
10 < 5
به فرض 10 توی این مسئله یک نوع داده‌ای خاص هست از کلاس
CustomInt
که من نوشتم و فراموش کردم براش __lt__ با کلاس Int خود پایتون رو پیاده سازی کنم اینجا اگر
return NotImplemented
رو برگردونم پایتون همینجا بهم خروجی نمیده بلکه شعورش انقدر بالاس که میره و
5 > 10
رو حساب می‌کنه ینی تو کلاس Int داخلی خودش متد __gt__ رو صدا میزنه تا ببینه می‌تونه شرط بالا رو ارزیابی کنه یا نه
اگر جواب داد که جواب رو برمیگردونه برای
10 < 5
اگر اینم پیاده سازی نشده بود NotImplemented در اون حالت ارور میده.


راجب موارد دیگه کدها اگر سوالی بود پیام بدید حتما جواب خواهم داد.


@PyHints
👌16👍6👏1
این سوالات احمقانه‌اس
که خب متأسفانه توی لینکدین و توییتر و اینستاگرام پر شده
و فقط وقتتون رو داره میگیره

بنظرم این موارد توهم زا هم هست، تازه‌کار فکر می‌کنه اینکه می‌تونه این سوالات رو جواب بده یعنی خیلی بلد هست.

ولی آیا واقعاً اهمیتی داره دونستن این موارد ! حتی اگر اینجوری کد بزنید.

تهش اینه ی print توی سورس کد می‌ذارید و خروجیش رو می‌بینید.

عمرتون رو صرف سوالات احمقانه نکنید، این اکانت‌ها رو هم معروف نکنید

شخصاً
Connection
رو روی لینکدین حذف می‌کنم وقتی می‌بینم کسی با این پست‌ها یا لایک کردن این پست‌ها باعث حواس پرتیم می‌شه.
دقیقاً این موارد حواشی برنامه‌نویسی هست
خیلی خیلی مراقب باشید.
👍98🙏6👌2👎1😁1🌚1
همونجوری که توی کامنت و گروه صحبت شد؛ و قبلا هم بسیار اشاره کردم توی موارد مختلف
EAFP (Easier to Ask Forgiveness than Permission)
مدل کد زدنی هست که توی core python هم دیده میشه حتی توی سورس کد اصلی که با C نوشته شده؛ این تغییر رو من توی یکی از سخنرانی های Guido van Rossum خالق پایتون شنیدم و توی لایو یکی از افراد مشهور ایرانی (اسم نمیبرم دیگه) که داشت میگفت سرعت پایتون 3.11 از 3.8 - 60% بیشتر نیست و دروغ هست هم بهش اشاره کردم.

داستان ازین قرار هست؛ توی پایتون 3.11 برای مثلا عملگر + اگر شما تا اینجای اجرای کد ۴-۵ بار فقط اعداد int رو باهم جمع زدید از این به بعد پایتون دیگه نوع داده رو چک نمی‌کنه بلکه از
EAFP
استفاده می‌کنه ینی فرض می‌کنه type ها int هست و سعی می‌کنه هر ۲ مورد رو باهم جمع بزنه ولی اگر exception بخوره در اون حالت تازه میره نوع داده هر دو argument رو چک می‌کنه و add رو مناسب اون type اجرا می‌کنه.

برای همین داشتن یک لیست از نوع داده‌ای
[int, float, str, int, float, str, ....]
توی پایتون ۳.۱۱ خیلی چیز بدی هست و باعث کند شدن اجرا میشه (بدتر از پایتون ۳.۸ چون چندین سربار به سیستم میدید؛ یک تلاش برای انجام و exception و بعد تازه type check درحالی که پایتون‌های قبل از ۳.۱۱ همون اول type check میکردند)

شنگتر اینه که ۳ تا لیست یا آرایه (پایتون لیست و آرایه باهم فرق داره پست بعدی) از ۳ نوع مختلف بسازید و بعد add رو اجرا کنید.

اگر فکر می‌کنید چقدر بد هست این ویژگی: مجدد فکر کنید (داری اشتباه میزنی)
ثابت شده بیش از ۹۶٪ موارد و مخصوصا توی کدهای اصولی این حالت درست هست و نوع داده‌ای ثابت می‌مونه زبان‌های برنامه‌نویسی دیگری هم هستند که ازین ویژگی استفاده می‌کنند. (روی static type ها فکر نکنید)


خلاصه که پایتون 3.11 هم EAFP استفاده می‌کنه و اینکه آپدیت شدن روی نسخه‌های پایتون فقط به نصب کردن نسخه جدیدتر نیست.


@PyHints
👌25👍71🍾1
همونطوری که گفتم توی پایتون
list, array 
۲ تا موضوع متفاوت از هم هست.
کار با لیست بخاطر خاصیت داینامیک بودن (هم از نظر سایز و حافظه و هم نوع داده‌ای) راحت تر هست اما همین دو ویژگی توی لیست باعث سرباز زیادی میشه

تصویر بالا مربوط به میزان مصرف حافظه
Array - List - Numpy
هست (داده مربوط به کار هوش مصنوعی)

اولین قدم توی optimization استفاده از نوع داده درست هست :
list —-> numpy array
3.8GB —-> 125MB
حساب کنید میزان بهبود در مصرف رم را


@PyHints
26👍19❤‍🔥51🎉1🍾1
حتما شما هم با with open توی پایتون کار کردید فوق‌العاده کمک کننده و مفید هست
همین که دیگه لازم نیست یادتون بمونه فایل رو ببیند یا اینکه کد درست رو بزنید
بستن فایل باید توی بخش finally باشه و ...
try:
excpet:
finally:

همین شرایط برای connection به دیتابیس هم هست.

with open

از یک راه حل تمیز و زیبا استفاده می‌کنه که بهش
Context Manager Protocol
گفته می‌شه
یک کلاس داخل تعریف پروتوکل
context manager 
قرار می‌گیره اگر ۲ تا متد رو داشته باشه

__enter__, __exit__

__enter__
دقیقا وقتی وارد بلوک
with .... :
pass

می‌شیه اجرا می‌شه و __exit__ وقتی از with خارج می‌شه
پس توی این بین میشه کارهای زیادی انجام داد

کد بالا مربوط به یکی از پروژه‌های بزرگ هست که توضیح میدم بدها
ی hot-fix که زدم و از print رو بجای logger استفاده کردم
توجه کنید خارج از with خروجی print مثل قبل چاپ میشه و دیگه توی فایلی نوشته نمیشه چون توی __exit__
sys.stdout
به مقدار قبلی برمیگرده.

@PyHints
👍21🔥71
Evenin
Jimmy Witherspoon
Evenin'
Artist: Jimmy Witherspoon
Album : Evenin' Blues
Released: 1964
Produce: 1963
Genres: Blues / Jazz

@PytensMusic
👍122👎1