fa
Feedback
Python Hints

Python Hints

رفتن به کانال در Telegram

Python tips and tricks The Good, Bad and the Ugly توی این کانال فقط قرار هست در مورد core python صحبت کنیم. این کانال یک بلاگ شخصی هست و پیرامون نظرات و چیزهایی که توی بیش از ۱۰ سال کد زدن یاد گرفتم (فقط برای کمک به دوستان تازه‌کار) Admin: @Abbasi_ai

نمایش بیشتر
9 607
مشترکین
-524 ساعت
+587 روز
+21130 روز
آرشیو پست ها
کامنت بذارید از حدس‌ها منم سطح کانال دستم میاد هممون هم اینجا داریم یاد میگیرم 🌹

یک مطلبی توی صحبت‌های دوستان به ذهنم اومد که راجبش صحبت نکردم سطح : Super Senior توی پستی که روش Reply زدم گفتم اگر list رو بخوایم از نظر حافظه بهینه کنیم بهتره از array, numpy استفاده کنیم. حالا اگر بخواهید سرعت list رو بالا ببرید می‌دونید چیکار باید بکنید ؟! (درحد سوال مصاحبه هم شاید ازتون پرسیده نشه هیچوقت بخاطر سطح بالای مطلب) حدس بزنید، پاسخ رو بعداً همینجا می‌نویسم، سر فرصت هم مثال خواهم زد.

مشکل اینه که خیلی از دوستان این حجم رو که می‌بینند سریع به load کردنش توی RAM فکر می‌کنند 10MB حجمی نیست، بعد کدهاشون رو تا جایی که توانش رو دارند Optimize می‌کنند و در نهایت هم وقتی نمی‌تونند بهبودش بدهند می‌گن پایتون سرعت کمی داره این موضوع قبول ولی بخشی ازین داستان برمیگرده به این موضوع که شما معماری سیستم‌ رو نمی‌شناسید و کاری رو قبول کردید که نیاز به این دانش داره اهمیت جدول بالا هم دقیقاً همینجا هست، ی موضوعی که همیشه توی کنفرانس‌ها و مراسم معرفی CPU ها اعلام می‌شه سرعت Compression, DeCompression هست، که ۹۹٪ بهش دقت نمی‌کنند. اما این نشون میده اگر من دیتای این مثال ینی ۱۰ مگابایت رو فشرده کنم و از cpu های نسل جدید هم استفاده کنم، می‌تونم دیتای فشرده شده رو وارد L3 Cache توی مثال بالا، کنم و بجای سرعت خوندن دیتای 100 ns از سرعت خوندن داده 30 ns بهره ببرم که خودش به تنهایی یعنی 1/3 شدن زمان، باقیشم بیخیال ... قطعاً جدول بالارو توی همه‌ی کتاب‌های درسی و ... دیدید اما از کاربردش هم اطلاع داشتید ؟ یا دلیل اینکه همیشه سرعت compression, decompression اعلام می‌شه رو چطور ؟ @PyHints

اهمیت این جدول خیلی مهمه، بعضی وقت‌ها توی مباحث Optimization شرکت که وارد می‌شیم، (البته برای pipeline های پردازشی که سالی ۱
اهمیت این جدول خیلی مهمه، بعضی وقت‌ها توی مباحث Optimization شرکت که وارد می‌شیم، (البته برای pipeline های پردازشی که سالی ۱ بار آپدیت می‌شوند و ۳۶۵ روز ۲۴ ساعت و ۷ روز هفته در حال پردازش دیتا هستند بدون تغییر حتی ۱ خط کد) یک همچین جدولی رو از تیم سخت‌افزار تحویل میگیرم؛ توی بحث ما Access Time رو کاری نداریم (چون فقط نسبت سرعت مهم هست و همین که ترتیب رو میدونیم کفایت می‌کنه) اما چیزی که اهمیت پیدا می‌کنه Size هست. اگر بخوام اهمیتش رو ساده توضیح بدم، فرض کنید روی کدهاتون Scalene رو اجرا کردید و دیدید که Cpu idle time یا همون زمان بیکاری cpu زیاد هست، و فرض کنید شما دارید دیتارو توی ram استفاده می‌کنید. فرض کنید سناریو realtime هست و این بخش حدوداً ۱۰ مگ دیتا در هر لحظه بهتون میده 10 MB خیلی حجم زیادی هست وقتی روی دیتای متنی کار می‌کنید. مشکل کجاست ؟ پست بعدی

راجب پروفایلر که قطعاً ی روزی سر فرصت مطلب می‌نویسم و آموزش میذارم مثل مطلبی که در مورد dis نوشتم و نحوه تحلیل خروجی‌ پروفایلر‌ها رو خواهم گفت چون صرف اینکه فقط زمان اجرا رو بخونید، بهش Profiling نمیگیم؛ نکته‌ای که متأسفانه ۹۰٪ آموزش‌ها در همین حد بهش می‌پردازند. اما تا اون زمان : ابزاری که خودم استفاده می‌کنم توی این سال‌ها Scalane Github هست (تلفظ درستش: اِسکِیلین) چراکه نه تنها برای Cpu بلکه Memory, Gpu هم اطلاعات profiling رو میده و الگوریتم‌هاش انقدر هوشمندانه نوشته شده که سرعت اجرا خوبی داره. Profiling شاید بنظر مطلب خیلی سطح بالایی باشه و نیروی سطح پایین‌تر فکر کنه که نمی‌تونه ازش بهره بگیره ولی اینطور نیست اتفاقا بیشترین کمک رو به نیرو‌های در مسیر یادگیری می‌‌تونه بکنه.

اینم سوال جالبی بود که از من شد (چند هفته گذشته ولی خب ...) اگر قرار بود از اول شروع کنی، چه مطالبی رو دنبالش میرفتی ؟ قطعاً برای برنا‌مه‌ نویسی : بجای اون همه جابجایی فقط ۳ تا زبان رو نگه می داشتم Assembly, Rust, Python3 نکته اینه که من خیلی آدم سمت ترمینال و سروری هستم و بیشتر جذب این موارد میشم تا محیط گرافیکی و ... قطعاً توی این مسیرم باز هم Cisco CCNA, CCNP رو میخوندم. قطعاً بازهم Linux RedHat رو آزمون‌هاش رو میدادم (مدرک lpic رو دوس ندارم چون خیلی کاغذی هست) این موارد واجباتی هستند که فکر می‌کنم خیلی از سواد امروزم رو مدیون یادگیریشون هستم.

برای راه حل راهکار زیاد هست : ۱- کش رو برای هر instance جدا کنیم؛ توی نمونه‌ کدهایی که ما داشتیم این راهکار برامون مناسب بود.
برای راه حل راهکار زیاد هست : ۱- کش رو برای هر instance جدا کنیم؛ توی نمونه‌ کدهایی که ما داشتیم این راهکار برامون مناسب بود. ۲- پردازش مربوط به این بخش که نیاز به cache داره رو کلا ببریم توی یک ماژول جدا و functional بنویسیم کدش رو ۳- بیایم از __new__ و meta class programming استفاده کنیم به همراه روش اول و اینطوری بین instance های مختلف هم می‌تونیم cache رو نگه داریم.

توی پستی که رفرنس دادم اگر نحوه صدا زدن تابع توسط decorator رو ندونید شاید یک مقدار سخت باشه اتصال این دوتا مطلب به هم دیگه د
توی پستی که رفرنس دادم اگر نحوه صدا زدن تابع توسط decorator رو ندونید شاید یک مقدار سخت باشه اتصال این دوتا مطلب به هم دیگه داخل کادر سبز کاری هست که واقعا lru_cache می‌کنه مشکل اینه که حالا که میره توی global دیگه garbage collector روش اعمال نمی‌شه چون همواره رفرنس خواهد داشت شاید بهتره توی این مثال
def __del__
رو هم بذارید و پرینت بزنید تا ببینید که اجرا نمی‌شه و این ینی garbage collector دست بهش نمیزنه حالا راه حل چیه : (پست بعدی)

ازونجایی که به جواب رسیدید مشکل اینه که lru_cache و cache (پایتون ۳.۹ به بعد) رو نباید روی method ها بزنیددایکومنت‌های مختلف
ازونجایی که به جواب رسیدید مشکل اینه که
lru_cache
و cache (پایتون ۳.۹ به بعد) رو نباید روی method ها بزنیددایکومنت‌های مختلف هم بهش اشاره کردند. دلیلش هم که قبلا توی این پست گفتم : بزودی در این مکان لینک قرار می‌گیرد توی پست بعدی بیشتر توضیح میدم.

جواب سوال اینجاس ☝️ اینم ی راهنمایی (گفته بودم انقدر ساده تو مصاحبه نمیاد) الان دقیقاً شده سوال مصاحبه‌ای 😬 سطح Mid-level, Senior

وقتی از chatGpt یا ابزارهای مشابه استفاده می‌کنید باید چندین برابر مراقب باشید. متاسفانه این ابزارها شعور درستی ندارند؛ شاید
وقتی از chatGpt یا ابزارهای مشابه استفاده می‌کنید باید چندین برابر مراقب باشید. متاسفانه این ابزارها شعور درستی ندارند؛ شاید مثل یک senior توضیح بدهند یا کد تمیز بزنند ولی درک درستی ندارند (برای همین من اصلا به نیروی
Junior, Mid-level 
حتی پیشنهاد نمی‌کنم) یک کد مشابه کد بالا باگی بود که توی کدهای پروژه پیدا کردم و چندروزی تیم رو هم درگیر کرده بود. بنظرتون علاوه بر موردی که با print مشخص کردم چه باگ فاجعه‌بار تری توی کدهای بالا وجود داره ؟

توی هفته گذشته به یک جمع‌بندی دیگه هم رسیدم درصد جوگیری توی ایران خیلی بالاس، Mojo رو قطعاً دیدید دیگه ؟ اگر ندیدید خوش بحالتون قبل ازین که جوگیر بشید، مثل ۱-۲ از همکارای مثلاً senior من توی جلسه بجای راهکار‌های Optimization راهکار بدید از mojo استفاده کنیم در نظر بگیرید: ۱- پروژه Typing توی پایتون که این روزا بسیار طرفدار داره توی دنیای پایتون : وقتی اولین بار توسعه داده شد، ایده اصلی این بود که Python static type بشه، که خود شخص Guido van Rossum متقاعدشون می‌کنه بجای اینکار Typing رو‌ اضافه کنند. ۲- این اولین بار نیست که اینکار داره انجام می‌شه یا تلاش می‌شه انجام بشه ولی خب شاید بهترین هست ۳- کسانی که پشت این پروژه هستند یک پروژه خوب دیگه هم دارند که چون استاندارد‌های صنعت رو رعایت نکرده بود هیچوقت صنعتی نشد FastAi منم بیشتر فکر می‌کنم Mojo بدرد Data science, ... میخوره نه پروژه صنعتی و نه software engineering ولی اگر دنبال ی چیز باحال میگردید که هم آینده داشته باشه هم وقت خالی شمارو پر کنه هم سرعت خوب بهتون تحویل بده Rust رو یاد بگیرید. درنهایت : لطفاً جوگیر نشید 🌹❤️

AdamJohnson-SpeedupyourDjangotests.pdf5.74 MB

مورد ۱، ۶، ۷ ۸۰-۹۰٪ سوالاتی که دوستان بصورت پیام خصوصی برای من می‌فرستند ازین به بعد جواب نخواهم داد چون باعث میشه سوالات مهم رو نتونم پاسخ بدم 🌹

چندتا نکته راجب پست‌های بالا : اگر این موارد رو بلد نبودید؛ بلد نیستید و یا حتی توضیحات بالا براتون سنگین هست : ۱- ممکنه من بد توضیح داده باشم (تایپش واقعا ۱۰ برابر توضیح رو سخت‌تر می‌کنه) ۲- یادتون نره سطح مباحث mid-level به بالا هست اونم mid-level واقعی نه ازینا که بعد از ۲ سال کار کردن سطح خودشون رو بالا میبرند. این پست استثنایی هست و سطح
Upper Senior 
هست پس اصلا نگران نشید. احتمالا بسیاری نیروی senior می‌بینید که حتی اگر اسم dis module رو شنیده باشند تفسیر کردنش رو بلد نیستند؛ بازم میگم چون نیازی نداشتند اما الان با جزئیات خوبی می‌دونید که دفعه بعدی که برای کدهای پایتونی و توی محیط توسعه مورد علاقتون debugger رو اجرا می‌کنید چطور عمل می‌کنه و مقادیر متغییرها؛ byte code؛ خونه حافظه و ... همرو بهتون نشون میده بخش عمده‌ای از اطلاعاتش رو ازینجا بدست میاره حالا علاوه بر اینها شاید درک کنید که چرا نوشتن از Profiler برام سخت هست (بیشترم بخاطر توضیح نحوه تفسیرش هست) در نهایت اگر سوالی بود تو گروه بپرسید؛ اگر نه که امیدوارم مفید باشه براتون لطفاْ reaction رو فراموش نکنید؛ وقتی کم می‌شه من فقط سیگنال میگیرم که اون پست یا موضوع رو دوست نداشتید و نمی‌خواید راجب اون یا موضوعات مشابه بشنوید (جدی میگم) دلیل ادامه ندادن بعضی مباحث هم همین هست واقعا روی تمامی پست ها reaction رو داشته باشیم لطفا ارادتمند عباسی @PyHints

خوندن خود dis از اجرا کردنش مهمتره اولین ستون از سمت چپ میگه که کدوم خط از کد باعث تولید byte code (ستون پنجم شده) بعنوان مثال توی کدهای من خط 13 سورس کد باعث تولید ۴ خط Byte code ایی که می‌بینید شد. ستون دوم : احتمالا نمی‌بینید این مورد رو توی کد بالا هم نیست (مثالی تو ذهنم نبود که این مورد رو توضیح بدم) اما نشون دهنده اینه که کدوم byte code توی خط به خط اجرا شده ستون سوم :
»
نشون دهنده JUMP هست ینی مثلا توی byte code مربوط به
FOR_ITER
قطعا یک JUMP داریم هربار که به انتهای for loop میرسیم باید برگردیم اولش و دستورات رو مجدد اجرا کنیم تا وقتی که شرط دیگه درست نباشه. ستون ۴: آدرس دهی byte code هست ینی توی مثال بالا آدرس همون FOR_ITER ایی که مثال زدیم توی byte code
8
هست. سوال مصاحبه‌‌ای که از من شد (برای
optimization tuning 
فک کنم RedHat و قبل از ادغام با IBM) البته سوال ساده‌ای بود ولی خب؛ دقت کنید فقط اعداد زوج هستند و هربار ۲ تا خونه حافظه جلو میره دلیلش اینه که
byte code
توی نسخه فعلی و این ورژن پایتون 3.8
2 Byte 
برای هر دستور استفاده می‌کنه بصورت دیفالت. ستون ۵ : opname اگر مصاحبه برای optimization خواستید شرکت کنید بهتره بطور کلی لیستش رو توی داکیومنت پایتون بخونید و اگر هم با Assembly کد زده باشید که می‌دونید داستان چی هست (دوستانی که امنیت کار می‌کنند و مهندسی معکوس حرفه‌ای هستند این مورد رو 😁) ستون ۶ : آرگومان مورد استفاده چه موردی که شما نیاز داری چه مواردی که خود پایتون بهشون نیاز داره بازم برگریدم به بایت کد مربوط به FOR_LOOP دقت کنید؛ ستون ۶ نوشته 12 که آدرس byte code بعدی درصورت درست بودن شرط for loop هست چون internal هست به نوعی استثنا هست (البته حقیقت اینه که استثنا نیست ولی چون توضیح و تفسیرش از همین حد الان هم advance تر هست ترجیح میدیم فعلا بعنوان استثنا ببینیمش) ستون ۷: اسم human readable اسم خوانا برای اینکه راحت بخونیم و بدونیم تغییرات روی کدوم متغییر تعریف شده توسط ما داره انجام‌ ‌می‌شه ولی بازم به FOR_ITER توجه کنید؛ روبروش برای ستون هفتم نوشته to 22 ینی وقتی شرط for loop درست نبود به این byte code منتقل بشه و ازینجا به بعد اجرا کنه کد رو و چون تو ستون اول نوشته ۹؛ می‌دونم که خط ۹ خارج از for loop من هست و دستور
return total
توی پایتون اجرا خواهد شد.

اول از همه این خروجی dis هست برای ۲ تا تابع مثال قبلی که با ======= از هم جدا شده؛ از تعداد operation مورد نیاز می‌شه فهمید ک
اول از همه این خروجی dis هست برای ۲ تا تابع مثال قبلی که با ======= از هم جدا شده؛ از تعداد operation مورد نیاز می‌شه فهمید که خب تابع دوم ینی sum چرا سریعتر هست برای اجرا هم اینطوری استفاده‌اش کنید import dis print(dis.dis(total_sum))

بگذریم ازین که اکثریت جوابی نمی‌دید. ولی حقیقتش این مثال رو نزدم که همگی بگید تابع total_sum و برای دلیل هم بگید که : چون sum توی Cpython پیاده سازی شده و بدون اینکه نیازی به ساخت Object های پایتونی داشته باشه می‌تونه عملیات ریاضی جمع زدن رو انجام بده و سربار چک کردن نوع Object و وجود متدهای مورد نیاز و object type و ... رو نداره (توجه کنید من روی ۳.۸ صحبت می‌کنم و نه ۳.۱۱ پس همه این موارد به نوعی صادق هست) تازه با C هم پیاده سازی می‌شه و سریعتر هست. که خب خودش جواب خیلی جزئی و درستی هست (همین که بگید توی C اجرا میشه هم جواب درست رو دادید) و نشون میده درک بالایی از پایتون دارید. من این مثال رو زدم تا شمارو با پکیج dis آشنا کنم راجب Profiling , همین dis قبلا صحبت کردم (توی کانال‌های دیگر) اما لازم بود اینجا هم صحبت کنم؛ Profiling رو حقیقتش دنبال مثالی هستم که بتونم توی نهایتا ۴ تا پست توضیحش بدم (بگذریم ازش) اما dis یک مرحله بالاتر هست. مثال بالا رو فعلا کامل فراموش کنید توی کار وقتایی پیش میاد که خروجی یک روش از روش دیگری سریعتر هست درحالی که منطق هر ۲ تا تابع یکسان هست توی این شرایط معمولا کاری که می‌کنند اینه که ی timeit میزنند و اون تابع رو چند ده یا چندصد بار اجرا می‌کنند مطمئن بشوند بطور میانگین چطوری هست profiling انجام میدیم که مطمئن بشیم p value به اندازی هست که نگیم رندم هست این بهبود زمانی و ... حالا بیاید فرض کنیم که بهبود واقعی هست ولی از نظر منطقی توی هر ۲ مورد یکسان هست توی این شرایط هیچ ابزاری نمی‌تونه کمک کنه به غیر از dis برگردیم به مثال قبل و توی پست بعدی ببینیم dis چیکار می‌کنه

بنظرتون کدوم تابع سریعتر هست ؟ دلیلش رو هم می‌دونید ؟ کد رو بهبود دادم (چون مجبور شدم لوکال اجرا کنم) که رم سیستم پر نشه الکی
بنظرتون کدوم تابع سریعتر هست ؟ دلیلش رو هم می‌دونید ؟ کد رو بهبود دادم (چون مجبور شدم لوکال اجرا کنم) که رم سیستم پر نشه الکی

به نظر شما بین این ۲ تا تابع کدوم سریعتر اجرا می‌شه ؟ دلیلش رو هم می‌دونید ؟
به نظر شما بین این ۲ تا تابع کدوم سریعتر اجرا می‌شه ؟ دلیلش رو هم می‌دونید ؟