Python Hints
الذهاب إلى القناة على Telegram
Python tips and tricks The Good, Bad and the Ugly توی این کانال فقط قرار هست در مورد core python صحبت کنیم. این کانال یک بلاگ شخصی هست و پیرامون نظرات و چیزهایی که توی بیش از ۱۰ سال کد زدن یاد گرفتم (فقط برای کمک به دوستان تازهکار) Admin: @Abbasi_ai
إظهار المزيد9 607
المشتركون
-524 ساعات
+587 أيام
+21130 أيام
أرشيف المشاركات
9 608
یک مطلبی توی صحبتهای دوستان به ذهنم اومد که راجبش صحبت نکردم
سطح :
Super Senior
توی پستی که روش
Reply
زدم گفتم اگر list رو بخوایم از نظر حافظه بهینه کنیم بهتره از array, numpy استفاده کنیم.
حالا اگر بخواهید سرعت list رو بالا ببرید میدونید چیکار باید بکنید ؟! (درحد سوال مصاحبه هم شاید ازتون پرسیده نشه هیچوقت بخاطر سطح بالای مطلب)
حدس بزنید، پاسخ رو بعداً همینجا مینویسم، سر فرصت هم مثال خواهم زد.
9 608
مشکل اینه که خیلی از دوستان این حجم رو که میبینند سریع به load کردنش توی RAM فکر میکنند 10MB حجمی نیست، بعد کدهاشون رو تا جایی که توانش رو دارند Optimize میکنند و در نهایت هم وقتی نمیتونند بهبودش بدهند میگن
پایتون سرعت کمی داره
این موضوع قبول ولی بخشی ازین داستان برمیگرده به این موضوع که شما معماری سیستم رو نمیشناسید و کاری رو قبول کردید که نیاز به این دانش داره
اهمیت جدول بالا هم دقیقاً همینجا هست، ی موضوعی که همیشه توی کنفرانسها و مراسم معرفی CPU ها اعلام میشه سرعت
Compression, DeCompression
هست، که ۹۹٪ بهش دقت نمیکنند.
اما این نشون میده اگر من دیتای این مثال ینی ۱۰ مگابایت رو فشرده کنم و از cpu های نسل جدید هم استفاده کنم، میتونم دیتای فشرده شده رو وارد
L3 Cache
توی مثال بالا، کنم و بجای سرعت خوندن دیتای
100 ns
از سرعت خوندن داده
30 ns
بهره ببرم که خودش به تنهایی یعنی
1/3
شدن زمان، باقیشم بیخیال ...
قطعاً جدول بالارو توی همهی کتابهای درسی و ... دیدید
اما از کاربردش هم اطلاع داشتید ؟
یا دلیل اینکه همیشه سرعت
compression, decompression
اعلام میشه رو چطور ؟
@PyHints
9 608
اهمیت این جدول خیلی مهمه،
بعضی وقتها توی مباحث
Optimization
شرکت که وارد میشیم، (البته برای pipeline های پردازشی که سالی ۱ بار آپدیت میشوند و ۳۶۵ روز ۲۴ ساعت و ۷ روز هفته در حال پردازش دیتا هستند بدون تغییر حتی ۱ خط کد)
یک همچین جدولی رو از تیم سختافزار تحویل میگیرم؛ توی بحث ما
Access Time
رو کاری نداریم (چون فقط نسبت سرعت مهم هست و همین که ترتیب رو میدونیم کفایت میکنه)
اما چیزی که اهمیت پیدا میکنه
Size
هست.
اگر بخوام اهمیتش رو ساده توضیح بدم، فرض کنید روی کدهاتون
Scalene
رو اجرا کردید و دیدید که
Cpu idle time
یا همون زمان بیکاری cpu زیاد هست، و فرض کنید شما دارید دیتارو توی ram استفاده میکنید.
فرض کنید سناریو realtime هست و این بخش حدوداً ۱۰ مگ دیتا در هر لحظه بهتون میده
10 MB
خیلی حجم زیادی هست وقتی روی دیتای متنی کار میکنید.
مشکل کجاست ؟ پست بعدی
9 608
راجب پروفایلر که قطعاً ی روزی سر فرصت مطلب مینویسم و آموزش میذارم مثل مطلبی که در مورد
dis
نوشتم و نحوه تحلیل خروجی پروفایلرها رو خواهم گفت چون صرف اینکه فقط زمان اجرا رو بخونید، بهش
Profiling
نمیگیم؛ نکتهای که متأسفانه ۹۰٪ آموزشها در همین حد بهش میپردازند.
اما تا اون زمان :
ابزاری که خودم استفاده میکنم توی این سالها
Scalane Github
هست (تلفظ درستش: اِسکِیلین)
چراکه نه تنها برای Cpu بلکه
Memory, Gpu
هم اطلاعات profiling رو میده و الگوریتمهاش انقدر هوشمندانه نوشته شده که سرعت اجرا خوبی داره.
Profiling
شاید بنظر مطلب خیلی سطح بالایی باشه و نیروی سطح پایینتر فکر کنه که نمیتونه ازش بهره بگیره
ولی اینطور نیست اتفاقا بیشترین کمک رو به نیروهای در مسیر یادگیری میتونه بکنه.9 608
اینم سوال جالبی بود که از من شد (چند هفته گذشته ولی خب ...)
اگر قرار بود از اول شروع کنی، چه مطالبی رو دنبالش میرفتی ؟
قطعاً برای برنامه نویسی :
بجای اون همه جابجایی فقط ۳ تا زبان رو نگه می داشتم
Assembly, Rust, Python3
نکته اینه که من خیلی آدم سمت ترمینال و سروری هستم و بیشتر جذب این موارد میشم تا محیط گرافیکی و ...
قطعاً توی این مسیرم باز هم
Cisco CCNA, CCNP
رو میخوندم.
قطعاً بازهم
Linux RedHat
رو آزمونهاش رو میدادم (مدرک lpic رو دوس ندارم چون خیلی کاغذی هست)
این موارد واجباتی هستند که فکر میکنم خیلی از سواد امروزم رو مدیون یادگیریشون هستم.
9 608
برای راه حل راهکار زیاد هست :
۱- کش رو برای هر
instance جدا کنیم؛ توی نمونه کدهایی که ما داشتیم این راهکار برامون مناسب بود.
۲- پردازش مربوط به این بخش که نیاز به cache داره رو کلا ببریم توی یک ماژول جدا و functional بنویسیم کدش رو
۳- بیایم از __new__ و meta class programming استفاده کنیم به همراه روش اول و اینطوری بین instance های مختلف هم میتونیم
cache
رو نگه داریم.9 608
توی پستی که رفرنس دادم اگر نحوه صدا زدن تابع توسط
decorator رو ندونید شاید یک مقدار سخت باشه اتصال این دوتا مطلب به هم دیگه
داخل کادر سبز کاری هست که واقعا lru_cache میکنه
مشکل اینه که حالا که میره توی global دیگه garbage collector روش اعمال نمیشه چون همواره رفرنس خواهد داشت
شاید بهتره توی این مثال
def __del__رو هم بذارید و پرینت بزنید تا ببینید که اجرا نمیشه و این ینی
garbage collector دست بهش نمیزنه
حالا راه حل چیه : (پست بعدی)9 608
ازونجایی که به جواب رسیدید
مشکل اینه که
lru_cacheو
cache (پایتون ۳.۹ به بعد) رو نباید روی
method
ها بزنیددایکومنتهای مختلف هم بهش اشاره کردند.
دلیلش هم که قبلا توی این پست گفتم :
بزودی در این مکان لینک قرار میگیرد
توی پست بعدی بیشتر توضیح میدم.9 608
جواب سوال اینجاس ☝️
اینم ی راهنمایی (گفته بودم انقدر ساده تو مصاحبه نمیاد)
الان دقیقاً شده سوال مصاحبهای 😬
سطح
Mid-level, Senior
9 608
وقتی از
chatGpt یا ابزارهای مشابه استفاده میکنید باید چندین برابر مراقب باشید.
متاسفانه این ابزارها شعور درستی ندارند؛ شاید مثل یک senior توضیح بدهند یا کد تمیز بزنند ولی درک درستی ندارند (برای همین من اصلا به نیروی
Junior, Mid-levelحتی پیشنهاد نمیکنم) یک کد مشابه کد بالا باگی بود که توی کدهای پروژه پیدا کردم و چندروزی تیم رو هم درگیر کرده بود. بنظرتون علاوه بر موردی که با
print مشخص کردم چه باگ فاجعهبار تری توی کدهای بالا وجود داره ؟9 608
توی هفته گذشته به یک جمعبندی دیگه هم رسیدم
درصد جوگیری توی ایران خیلی بالاس،
Mojo
رو قطعاً دیدید دیگه ؟
اگر ندیدید خوش بحالتون
قبل ازین که جوگیر بشید، مثل ۱-۲ از همکارای مثلاً senior من توی جلسه بجای راهکارهای
Optimization
راهکار بدید از mojo استفاده کنیم در نظر بگیرید:
۱- پروژه Typing توی پایتون که این روزا بسیار طرفدار داره توی دنیای پایتون :
وقتی اولین بار توسعه داده شد، ایده اصلی این بود که
Python static type
بشه، که خود شخص
Guido van Rossum
متقاعدشون میکنه بجای اینکار Typing رو اضافه کنند.
۲- این اولین بار نیست که اینکار داره انجام میشه یا تلاش میشه انجام بشه ولی خب شاید بهترین هست
۳- کسانی که پشت این پروژه هستند یک پروژه خوب دیگه هم دارند که چون استانداردهای صنعت رو رعایت نکرده بود هیچوقت صنعتی نشد
FastAi
منم بیشتر فکر میکنم
Mojo
بدرد
Data science, ...
میخوره نه پروژه صنعتی و نه software engineering
ولی اگر دنبال ی چیز باحال میگردید که هم آینده داشته باشه هم وقت خالی شمارو پر کنه هم سرعت خوب بهتون تحویل بده
Rust
رو یاد بگیرید.
درنهایت : لطفاً جوگیر نشید 🌹❤️
9 608
مورد ۱، ۶، ۷
۸۰-۹۰٪ سوالاتی که دوستان بصورت پیام خصوصی برای من میفرستند
ازین به بعد جواب نخواهم داد
چون باعث میشه سوالات مهم رو نتونم پاسخ بدم 🌹
9 608
چندتا نکته راجب پستهای بالا :
اگر این موارد رو بلد نبودید؛ بلد نیستید و یا حتی توضیحات بالا براتون سنگین هست :
۱- ممکنه من بد توضیح داده باشم (تایپش واقعا ۱۰ برابر توضیح رو سختتر میکنه)
۲- یادتون نره سطح مباحث mid-level به بالا هست اونم mid-level واقعی نه ازینا که بعد از ۲ سال کار کردن سطح خودشون رو بالا میبرند.
این پست استثنایی هست و سطح
Upper Seniorهست پس اصلا نگران نشید. احتمالا بسیاری نیروی
senior میبینید که حتی اگر اسم
dis module
رو شنیده باشند تفسیر کردنش رو بلد نیستند؛ بازم میگم چون نیازی نداشتند
اما الان با جزئیات خوبی میدونید که دفعه بعدی که برای کدهای پایتونی و توی محیط توسعه مورد علاقتون
debugger
رو اجرا میکنید چطور عمل میکنه و مقادیر متغییرها؛ byte code؛ خونه حافظه و ... همرو بهتون نشون میده بخش عمدهای از اطلاعاتش رو ازینجا بدست میاره
حالا علاوه بر اینها شاید درک کنید که چرا نوشتن از Profiler برام سخت هست (بیشترم بخاطر توضیح نحوه تفسیرش هست)
در نهایت اگر سوالی بود تو گروه بپرسید؛ اگر نه که
امیدوارم مفید باشه براتون
لطفاْ reaction رو فراموش نکنید؛ وقتی کم میشه من فقط سیگنال میگیرم که اون پست یا موضوع رو دوست نداشتید و نمیخواید راجب اون یا موضوعات مشابه بشنوید (جدی میگم) دلیل ادامه ندادن بعضی مباحث هم همین هست واقعا
روی تمامی پست ها reaction رو داشته باشیم لطفا
ارادتمند عباسی
@PyHints9 608
خوندن خود
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توی پایتون اجرا خواهد شد.
9 608
اول از همه این خروجی
dis هست برای ۲ تا تابع مثال قبلی که با
=======
از هم جدا شده؛ از تعداد operation مورد نیاز میشه فهمید که خب تابع دوم ینی sum چرا سریعتر هست برای اجرا هم اینطوری استفادهاش کنید
import dis
print(dis.dis(total_sum))9 608
بگذریم ازین که اکثریت جوابی نمیدید.
ولی حقیقتش این مثال رو نزدم که همگی بگید تابع
total_sum
و برای دلیل هم بگید که :
چون sum توی Cpython پیاده سازی شده و بدون اینکه نیازی به ساخت Object های پایتونی داشته باشه میتونه عملیات ریاضی جمع زدن رو انجام بده و سربار چک کردن نوع Object و وجود متدهای مورد نیاز و object type و ... رو نداره (توجه کنید من روی ۳.۸ صحبت میکنم و نه ۳.۱۱ پس همه این موارد به نوعی صادق هست) تازه با C هم پیاده سازی میشه و سریعتر هست.
که خب خودش جواب خیلی جزئی و درستی هست (همین که بگید توی C اجرا میشه هم جواب درست رو دادید) و نشون میده درک بالایی از پایتون دارید.
من این مثال رو زدم تا شمارو با پکیج
dis
آشنا کنم راجب Profiling , همین dis قبلا صحبت کردم (توی کانالهای دیگر) اما لازم بود اینجا هم صحبت کنم؛
Profiling
رو حقیقتش دنبال مثالی هستم که بتونم توی نهایتا ۴ تا پست توضیحش بدم (بگذریم ازش) اما dis یک مرحله بالاتر هست.
مثال بالا رو فعلا کامل فراموش کنید
توی کار وقتایی پیش میاد که خروجی یک روش از روش دیگری سریعتر هست درحالی که منطق هر ۲ تا تابع یکسان هست
توی این شرایط معمولا کاری که میکنند اینه که
ی timeit میزنند و اون تابع رو چند ده یا چندصد بار اجرا میکنند مطمئن بشوند بطور میانگین چطوری هست
profiling
انجام میدیم که مطمئن بشیم p value به اندازی هست که نگیم رندم هست این بهبود زمانی و ...
حالا بیاید فرض کنیم که بهبود واقعی هست ولی از نظر منطقی توی هر ۲ مورد یکسان هست توی این شرایط هیچ ابزاری نمیتونه کمک کنه به غیر از
dis
برگردیم به مثال قبل و توی پست بعدی ببینیم dis چیکار میکنه9 608
بنظرتون کدوم تابع سریعتر هست ؟
دلیلش رو هم میدونید ؟
کد رو بهبود دادم (چون مجبور شدم لوکال اجرا کنم) که رم سیستم پر نشه الکی
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
