گروه هکری که قبلا به اطلاعات تپسی دسترسی پیدا کرده بود، مدعی هک اسنپفود شد و برخی اطلاعات (شامل اطلاعات ۱۰۰۰ کاربر و...) را به عنوان دیتای نمونه منتشر کرد.
✔️ کلاس zip
ببینید zip یک کلاس هست که میاد به عنوان پارامتر های ورودی خودش،
شاید بگید
خوب حالا این zip چطوری کار میکنه 🤔
این کلاس میاد و از
نکته مهم ❗️
کلاس zip هم مثل filter و map و ... یک
مثال 🧪
پس
ببینید zip یک کلاس هست که میاد به عنوان پارامتر های ورودی خودش،
iterable
(یا iterable
هایی) رو به صورت postional argument
میگیره و یک zip object
به ما برمیگردونه!شاید بگید
iterable
چیه؟ iterable
میشه چیزی که شما توی پایتون بتونی مثلا روش for
بزنی و به اصطلاح iterate
کنی! مثل چی؟ مثل list - str - tuple و ...خوب حالا این zip چطوری کار میکنه 🤔
این کلاس میاد و از
iterable
هایی که بهش داده شده، به تعداد اون Iterable
ها (فرض کنیم n
تا) tuple (هایی) به سایز n
برامون yield
میکنه! حالا اعضای اون tuple که سایزش n
هست (یعنی n
تا عضو داره) چی هستن؟ zip میاد و اولین عضو رو از اولین iterable
و دومین عضو رو از دومین iterable
و همینطوری تا آخر میگیره! این تا کی ادامه داره؟ تا زمانی که اعضای کوتاه ترین iterable
تمام بشه!نکته مهم ❗️
کلاس zip هم مثل filter و map و ... یک
lazy iterator
هست، یعنی چی؟ یعنی جواب رو درجا برای ما محاسبه نمیکنه و هر بار که روش next زده بشه، به ما یک چیزی yield میکنه.مثال 🧪
names = [الان هر بار که روی z ما
"Ali",
"Mohsen",
"Hassan",
]
last_names = [
"Hassanzadeh",
"Mohammadi",
]
z = zip(names, last_names)
next
بزنیم به ما یک tuple به سایز 2 میده (چرا 2 ؟ چون 2 تا iterable
بهش دادیم)>>> next(z)به همین صورت میتونید به لیست، ست و ... این
('Ali', 'Hassanzadeh')
zip object
رو تبدیل کنید:>>> list(z)چرا هر tuple دوتا عضو بیشتر نداره؟ چون همونطور که بالا گفتم تعداد به اندازه کوتاه ترین
[('Ali', 'Hassanzadeh'), ('Mohsen', 'Mohammadi')]
iterable
هست که در اینجا last_names
کوتاه تر هست و فقط 2 عضو داره!پس
signature
کلی کلاس zip به شکل زیر هست (از پایتون 3.10 پارامتر strict
بهش اضافه شده که توضیحش میدم)zip(*iterables, strict=False) —> zip objectخوب ی نکته میمونه، اینکه از پایتون 3.10 به این کلاس یک پارامتری اضافه شده به اسم
strict
! کارش چیه؟ مقدارش به صورت پیشفرض False
هست، ولی زمانی که شما اون رو True کنید، چک میکنه که همه iterable
هایی که بهش دادید آیا طول یکسان دارند یا نه و اگر این شرایط برقرار نبود یک خطای ValueError
به شما میده! مثال:names = [خروجی:
"Ali",
"Mohsen",
"Hassan",
]
last_names = [
"Hassanzadeh",
"Mohammadi",
]
print(list(zip(names, last_names, strict=True)))
ValueError: zip() argument 2 is shorter than argument 1
#builtins✔️ کلاس map
کلاس
این تایپ برای اولین پارامتر یک
اول از همه تایپ مپ درست مانند
کاری که
چند مثال کاربردی 🧪
تبدیل همه اعداد یک لیست به مربع خودشان:
اگر به
کلاس
map
یکی دیگه از تایپهای built-in پایتون است.این تایپ برای اولین پارامتر یک
Callable
دریافت میکنه (مثلا یک تابع یا یک کلاس که داندر ____call____ رو پیادهسازی میکنه) و پارامتر بعدیش تعداد متغیری iterable
هست که بعد از callable
بهش پاس میدیم. signature
عه تابع مپ به این شکل هست:map(callable, *iterables) —> map objectاما
map
چه کاری انجام میده؟ 🤔اول از همه تایپ مپ درست مانند
range
و فیلتر lazy iterator
هست، یعنی فوری نتایج رو محاسبه نمیکنه،کاری که
map
میکنه اینه که میاد دونه دونه از اون iterable
(یا iterable
هایی) که بهش داده شده، به اون callable
پاس میده و نتیجه ای که اون callable
بهش داده (در واقع مقداری که از callable
ما return
شده) رو هر بار که ما next
میزنیم به ما برمیگردونه!چند مثال کاربردی 🧪
تبدیل همه اعداد یک لیست به مربع خودشان:
lst = [2, 4, 6, 8]Output:
print(list(map(lambda x: x ** 2, lst)))
[4, 16, 36, 64]
تبدیل تمام استرینگهای یک لیست به شکل Uppercase خودشان:lst = ["John", "David", "Mike"]Output:
print(list(map(str.upper, lst)))
['JOHN', 'DAVID', 'MIKE']
نکته مهم ❗️اگر به
map
چند تا iterable
میدید، باید حواستون باشه که اون callable
باید به تعداد iterable
ها پارامتر داشته باشه! مثال:x = list(map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6]))Output:
print(x)
[5, 7, 9]
در مثال بالا دو تا iterable
به مپ پاس دادیم پس باید تابعی که به map
میدیم دوتا آرگومان بگیره. حالا map
میاد پارامتر اول (یعنی x) رو از اولین iterable
و دومی رو (یعنی y) از دومین iterable
میگیره! نکته قابل توجه دیگه اینکه، این فرایند توی تابع (یعنی جمع x و y) به تعداد اعضای کوتاه ترین iterable
انجام میشه! یعنی اگر یکی از iterable
ها 2 عضو داشت و بقیه 5 عضو، فقط روی 2 عضو اول هر iterable
مپ کار انجام میده! مثال:x = list(map(lambda x, y: x + y, [2, 3], [4, 5, 6, 4]))Output:
print(x)
[6, 8]
#builtinsهیچوقت نباید اسم ماژولی که داریم داخلش کد میزنیم رو اسم یکی از ماژول/پکیج های خود پایتون یا ماژول/پکیج هایی که نصب کردیمشون تا استفاده کنیم قرار بدیم...
مثال: من قرار هست با تاریخ کمی کار کنم و خب ماژول datetime رو که پایتون توی استاندارد لایبرری گذاشته رو import میکنم. ولی اسم فایل یا ماژولی که دارم کد میزنم داخلش رو میذارم datetime.py !
# datetime.py
import datetime
t = datetime.date(2020, 10, 10)
print(t)
اروری دریافت میکنم :
AttributeError: partially initialized module 'datetime' has no attribute 'date' (most likely due to a circular import)
این ارور تا حدی خوبه یه چیزایی داره بهمون راجع partially initialized شدن و همچنین circular import میگه...
سناریوی بد موقعی هست که اسم فایلی که دارم توش کد میزنم datetime نیست ولی کنار فایلم توی "همون پوشه" یه فایل به اسم datetime.py به اشتباه درست کردم و خالی هست... حالا چی :
# main.py
import datetime
t = datetime.date(2020, 10, 10)
print(t)
متن ارور :
AttributeError: module 'datetime' has no attribute 'date'
این جا دیگه نه تنها کمک نمیکنه بلکه باعث میشه اول فکر کنیم که خب آها حتما این ماژول قبلا attribute عه date رو داشته الان حذف کردن برم ببینم معادلش چیه! یا اگه مثلا datetime ماژولی بوده باشه که نصب کرده بودیم، حتما ما ورژن دیگه ای ازشو نصب کردیم... ما که عین کدی که مثلا توی ویدیو آموزشی هست رو داریم میزنیم چرا میگه date رو نداره ؟؟
ماجرا از این قرار هست که وقتی دارید یه ماژولی رو import میکنید ، پایتون یه مسیر های مشخصی رو برای پیدا کردن اون ماژول طی میکنه که میتونید با پرینت کردن sys.path ببینید :
import sys
for path in sys.path:
print(path)
توی ویندوز حدودا(ممکنه بسته به نسخه پایتون و platform ترتیبش فرق کنه یا کم و زیاد باشه ما کاری به این قضیه نداریم) به این شکل هست: (اون فولدر test فولدری هست که ماژولی که داره ران میشه داخلش هست)
C:\Users\usr\Desktop\test
C:\Users\usr\...\Python39\python39.zip
C:\Users\usr\...\Python39\DLLs
C:\Users\usr\...\Python39\lib
C:\Users\usr\...\Python39
C:\Users\usr\...\Python39\lib\site-packages
پایتون این مسیر هارو "به ترتیب" از بالا تا پایین چک میکنه تا ماژولی که اسمشو جلوی import statement زدیم رو پیدا کنه و "به محض" اینکه بهش برسه همون رو برای ما import میکنه.
به مسیر ها نگاه کنید: اولین مسیر همیشه مسیری هست که script شما داخلش هست. (اگه PYTHONPATH رو set کرده باشید به عنوان مسیر دوم بعد از current directory اضافه میشه به sys.path. ) یه مسیر دیگه اون folder عه site-packages هست که میبینید. این دقیقا همونجایی هست که پکیج هایی که نصب میکنید داخلش میرن. باقی مسیر ها هم برای ماژول های دیگه ی پایتون هستند.
حالا میتونیم دلیلشو متوجه بشیم چرا پایتون توی هر دو مثالی که اول پست زدیم اول پکیج مارو پیدا کرد... site-package و فولدر های دیگه ای که ماژول های خود پایتون داخلش هستن "بعد" از اولین مسیری که داخل لیست دیدیم سرچ میشن پس در نتیجه اینجا datetime داره اشاره میکنه به همین ماژولی که داریم توش کد میزنیم(مثال اول) یا اون ماژول datetime ای که کنار فایمون ساختیم (مثال دوم)... اونو پایتون پیدا میکنه و میاره و خب طبیعتا ما چیزی به عنوان "date" تعریف نکرده بودیم !!
اگه کمی کلی تر بخوایم بگیم در واقع "هرجا" از این مسیرها یه فایل datetime.py قرار بدیم که نسبت به اونی که پایتون توی استاندارد لایبرری قرار داده جلوتر باشه این مشکل رو داریم...
سوال: همه ی ماژول ها به همین صورت هستن ؟ نه ! اون هایی که داخل مفسر compile شدن شامل موارد بالا نمیشن یعنی اگه اسم فایلتون رو این اسامی بذارین باعث نمیشه پایتون اونارو پیدا کنه اول. اینجوری ببینینشون :
import sys
for i in sys.builtin_module_names:
print(i)
هیچوقت مثلا gc.py شما زود تر پیدا نمیشه.
مثال: من قرار هست با تاریخ کمی کار کنم و خب ماژول datetime رو که پایتون توی استاندارد لایبرری گذاشته رو import میکنم. ولی اسم فایل یا ماژولی که دارم کد میزنم داخلش رو میذارم datetime.py !
# datetime.py
import datetime
t = datetime.date(2020, 10, 10)
print(t)
اروری دریافت میکنم :
AttributeError: partially initialized module 'datetime' has no attribute 'date' (most likely due to a circular import)
این ارور تا حدی خوبه یه چیزایی داره بهمون راجع partially initialized شدن و همچنین circular import میگه...
سناریوی بد موقعی هست که اسم فایلی که دارم توش کد میزنم datetime نیست ولی کنار فایلم توی "همون پوشه" یه فایل به اسم datetime.py به اشتباه درست کردم و خالی هست... حالا چی :
# main.py
import datetime
t = datetime.date(2020, 10, 10)
print(t)
متن ارور :
AttributeError: module 'datetime' has no attribute 'date'
این جا دیگه نه تنها کمک نمیکنه بلکه باعث میشه اول فکر کنیم که خب آها حتما این ماژول قبلا attribute عه date رو داشته الان حذف کردن برم ببینم معادلش چیه! یا اگه مثلا datetime ماژولی بوده باشه که نصب کرده بودیم، حتما ما ورژن دیگه ای ازشو نصب کردیم... ما که عین کدی که مثلا توی ویدیو آموزشی هست رو داریم میزنیم چرا میگه date رو نداره ؟؟
ماجرا از این قرار هست که وقتی دارید یه ماژولی رو import میکنید ، پایتون یه مسیر های مشخصی رو برای پیدا کردن اون ماژول طی میکنه که میتونید با پرینت کردن sys.path ببینید :
import sys
for path in sys.path:
print(path)
توی ویندوز حدودا(ممکنه بسته به نسخه پایتون و platform ترتیبش فرق کنه یا کم و زیاد باشه ما کاری به این قضیه نداریم) به این شکل هست: (اون فولدر test فولدری هست که ماژولی که داره ران میشه داخلش هست)
C:\Users\usr\Desktop\test
C:\Users\usr\...\Python39\python39.zip
C:\Users\usr\...\Python39\DLLs
C:\Users\usr\...\Python39\lib
C:\Users\usr\...\Python39
C:\Users\usr\...\Python39\lib\site-packages
پایتون این مسیر هارو "به ترتیب" از بالا تا پایین چک میکنه تا ماژولی که اسمشو جلوی import statement زدیم رو پیدا کنه و "به محض" اینکه بهش برسه همون رو برای ما import میکنه.
به مسیر ها نگاه کنید: اولین مسیر همیشه مسیری هست که script شما داخلش هست. (اگه PYTHONPATH رو set کرده باشید به عنوان مسیر دوم بعد از current directory اضافه میشه به sys.path. ) یه مسیر دیگه اون folder عه site-packages هست که میبینید. این دقیقا همونجایی هست که پکیج هایی که نصب میکنید داخلش میرن. باقی مسیر ها هم برای ماژول های دیگه ی پایتون هستند.
حالا میتونیم دلیلشو متوجه بشیم چرا پایتون توی هر دو مثالی که اول پست زدیم اول پکیج مارو پیدا کرد... site-package و فولدر های دیگه ای که ماژول های خود پایتون داخلش هستن "بعد" از اولین مسیری که داخل لیست دیدیم سرچ میشن پس در نتیجه اینجا datetime داره اشاره میکنه به همین ماژولی که داریم توش کد میزنیم(مثال اول) یا اون ماژول datetime ای که کنار فایمون ساختیم (مثال دوم)... اونو پایتون پیدا میکنه و میاره و خب طبیعتا ما چیزی به عنوان "date" تعریف نکرده بودیم !!
اگه کمی کلی تر بخوایم بگیم در واقع "هرجا" از این مسیرها یه فایل datetime.py قرار بدیم که نسبت به اونی که پایتون توی استاندارد لایبرری قرار داده جلوتر باشه این مشکل رو داریم...
سوال: همه ی ماژول ها به همین صورت هستن ؟ نه ! اون هایی که داخل مفسر compile شدن شامل موارد بالا نمیشن یعنی اگه اسم فایلتون رو این اسامی بذارین باعث نمیشه پایتون اونارو پیدا کنه اول. اینجوری ببینینشون :
import sys
for i in sys.builtin_module_names:
print(i)
هیچوقت مثلا gc.py شما زود تر پیدا نمیشه.
درود.
میخواستم درباره ی آبجکت معروف و شناخته شده ی generator حرف بزنیم ولی با نگاه کمی متفاوتتر تا به این برسیم که دقیقا چطور کار میکنه و چطور پیداش شد. نیاز هست که کمی حرف های پیش نیاز بزنیم صبور باشید.
قبل از هر چیزی درباره ی خود فانکشن حرف بزنیم؛ ولی نه تو پایتون بلکه تو C:
وقتی یه فانکشنی کال میشه، توی call stack یک frame جدید میاد که برای اون فانکشن هست. این frame شامل تمام متغیر های لوکال و پارامتر های اون فانکشنه. وقتی فانکشن تموم میشه چه اتفاقی میفته؟ اون frame از stack پاپ میشه (یا دقیق ترش stack pointer کم میشه)
و نکته اینجاس که هرچی که توی اون frame هست دیگه قابل دسترس نیست و اگر استفادشون کنیم، undefined behavior هست. چرا؟ چون توی "مموری استک" این frame قرار داده شده بود و اون فضا الان آزاد شده و قابل استفاده هست برای بقیه (توی پرانتز، در C که مدیریت حافظه نداره، باید آبجکت هایی که توی heap میسازیم رو خودمون مدیریت کنیم نه استک):
با اینکه آدرسش رو return کردیم ولی باز هم نمیتونیم به آیتم های لیست دسترسی داشته باشیم.
حالا اینارو گفتم که موضوع مهمی رو بگم. اونم اینه که تو پایتون هم همین call stack و اینا هست ولی اون frame object توی heap ساخته میشه. این یعنی اگر بخوایم میتونیم اون رو ذخیره داشته باشیم و همیشه بمونه! مثلا مانع از نابود شدن خودش و آبجکت های درونش بشیم. تو مثال زیر
خب حالا که اینو گفتیم بریم سراغ خود آبجکت فانکشن تو پایتون. وقتی فانکشن کال میشه یه frame object ساخته میشه. این frame object داخلش آبجکت های زیادی هست (مستقیم یا غیرمستقیم) از جمله رفرنس داره به متغیر های داخل اون namespace و رفرنسی داره به code object که یک unit ئه executable هست. داخل این code object ما bytecode ها رو داریم که همون instruction ها هستن.
درواقع instruction ها هستن که اجرا میشن و این state ذخیره میشه. تو کد زیر
خب حالا بخش جالب ماجرا اینجاست. ما به عنوان طراحان فرضی زبان پایتون، میدونیم که frame ما میتونه خارج از موقع کال شدن هم زنده بمونه + از طرفی به state هم که دسترسی داریم. ( اینکه الان متغیر های local چیا هستن، اینکه الان تا instruction چندم اجرا شده و غیره)
فقط یه مشکلی هست، فانکشن های ما وقتی کال میشن از اولین instruction تا آخرینش رو اجرا میکنن و تموم میشن و همه ی آبجکت های داخل اون frame از بین میرن (اگر رفرنس دیگه ای نداشته باشن جای دیگه).
الان همه چیز محیا هست برای اینکه یه ساختار یا keyword جدیدی بیاریم تو زبان که هرجایی از execution فانکشن خواستیم بتونیم pause کنیم و اون رو با هر state ای که داره به حال خودش رها کنیم.
بیایم yield رو معرفی کنیم! هروقت yield اومد، کافیه اجرا رو متوقف کنیم و مثل فانکشن ها (که بعد از تموم شدنشون، frame شون از stack frame جدا میشن) frame این generator ها رو هم جدا کنیم.
بعدا اگه خواستیم generator رو ادامه بدیم و روش next بزنیم (مستقیم خودمون یا غیر مستقیم توسط پایتون) تنها کاری که باید بکنیم اینه که frameش رو برداریم و بچسبونیم به stack frame ممون و از اون state ای که بودیم ادامه بدیم.
این call stack با linked list پیاده سازی شده و frame ها نود های اون هستن. با
جنریتور ها با وجود سرعت خوبی که دارن، برای سرعت بیشتر ساخته نشدن بلکه برای استفاده بهینهتر از مموری ساخته شدن. داشتن همچین آبجکتی (به اضافه ساختار هایی مثل
میخواستم درباره ی آبجکت معروف و شناخته شده ی generator حرف بزنیم ولی با نگاه کمی متفاوتتر تا به این برسیم که دقیقا چطور کار میکنه و چطور پیداش شد. نیاز هست که کمی حرف های پیش نیاز بزنیم صبور باشید.
قبل از هر چیزی درباره ی خود فانکشن حرف بزنیم؛ ولی نه تو پایتون بلکه تو C:
وقتی یه فانکشنی کال میشه، توی call stack یک frame جدید میاد که برای اون فانکشن هست. این frame شامل تمام متغیر های لوکال و پارامتر های اون فانکشنه. وقتی فانکشن تموم میشه چه اتفاقی میفته؟ اون frame از stack پاپ میشه (یا دقیق ترش stack pointer کم میشه)
و نکته اینجاس که هرچی که توی اون frame هست دیگه قابل دسترس نیست و اگر استفادشون کنیم، undefined behavior هست. چرا؟ چون توی "مموری استک" این frame قرار داده شده بود و اون فضا الان آزاد شده و قابل استفاده هست برای بقیه (توی پرانتز، در C که مدیریت حافظه نداره، باید آبجکت هایی که توی heap میسازیم رو خودمون مدیریت کنیم نه استک):
int *returnArray() {
int arr[3] = {11, 22, 33};
printf("%p\n", arr);
printf("%d\n", arr[1]);
return &arr;
}
int main(void) {
int *arr;
arr = returnArray();
printf("%p\n", arr);
printf("%d\n", arr[1]); // ???
}
با اینکه آدرسش رو return کردیم ولی باز هم نمیتونیم به آیتم های لیست دسترسی داشته باشیم.
حالا اینارو گفتم که موضوع مهمی رو بگم. اونم اینه که تو پایتون هم همین call stack و اینا هست ولی اون frame object توی heap ساخته میشه. این یعنی اگر بخوایم میتونیم اون رو ذخیره داشته باشیم و همیشه بمونه! مثلا مانع از نابود شدن خودش و آبجکت های درونش بشیم. تو مثال زیر
global f
رو اگه از کامنت در بیارید obj از بین نمیره چون frame رو ذخیره کردیم:from gc import collect
from sys import _getframe
class A:
def __del__(self):
print("del called")
def fn():
# global f
f = _getframe(0)
obj = A()
fn()
collect()
input()
خب حالا که اینو گفتیم بریم سراغ خود آبجکت فانکشن تو پایتون. وقتی فانکشن کال میشه یه frame object ساخته میشه. این frame object داخلش آبجکت های زیادی هست (مستقیم یا غیرمستقیم) از جمله رفرنس داره به متغیر های داخل اون namespace و رفرنسی داره به code object که یک unit ئه executable هست. داخل این code object ما bytecode ها رو داریم که همون instruction ها هستن.
درواقع instruction ها هستن که اجرا میشن و این state ذخیره میشه. تو کد زیر
lasti
یعنی last instruction. (توی cpu هم اتفاق مشابهی میفته. اینجا pvm میخواد بدونه چی رو اجرا کرده و حالا نوبت چیه):from sys import _getframe
def fn():
print(_getframe(0).f_lasti)
a = 10
print(_getframe(0).f_lasti)
fn()
خب حالا بخش جالب ماجرا اینجاست. ما به عنوان طراحان فرضی زبان پایتون، میدونیم که frame ما میتونه خارج از موقع کال شدن هم زنده بمونه + از طرفی به state هم که دسترسی داریم. ( اینکه الان متغیر های local چیا هستن، اینکه الان تا instruction چندم اجرا شده و غیره)
فقط یه مشکلی هست، فانکشن های ما وقتی کال میشن از اولین instruction تا آخرینش رو اجرا میکنن و تموم میشن و همه ی آبجکت های داخل اون frame از بین میرن (اگر رفرنس دیگه ای نداشته باشن جای دیگه).
الان همه چیز محیا هست برای اینکه یه ساختار یا keyword جدیدی بیاریم تو زبان که هرجایی از execution فانکشن خواستیم بتونیم pause کنیم و اون رو با هر state ای که داره به حال خودش رها کنیم.
بیایم yield رو معرفی کنیم! هروقت yield اومد، کافیه اجرا رو متوقف کنیم و مثل فانکشن ها (که بعد از تموم شدنشون، frame شون از stack frame جدا میشن) frame این generator ها رو هم جدا کنیم.
بعدا اگه خواستیم generator رو ادامه بدیم و روش next بزنیم (مستقیم خودمون یا غیر مستقیم توسط پایتون) تنها کاری که باید بکنیم اینه که frameش رو برداریم و بچسبونیم به stack frame ممون و از اون state ای که بودیم ادامه بدیم.
def gen():
a = 1
yield
b = 1
yield
g = gen()
next(g)
print(g.gi_frame.f_lasti, g.gi_frame.f_locals)
next(g)
print(g.gi_frame.f_lasti, g.gi_frame.f_locals)
این call stack با linked list پیاده سازی شده و frame ها نود های اون هستن. با
f_back
به frame قبلی اشاره میکنن به راحتی وصل میشن و جدا میشن.جنریتور ها با وجود سرعت خوبی که دارن، برای سرعت بیشتر ساخته نشدن بلکه برای استفاده بهینهتر از مموری ساخته شدن. داشتن همچین آبجکتی (به اضافه ساختار هایی مثل
yield from
) میتونه زمینه خیلی چیز ها رو فراهم کنه. از جمله فریموورک هایی مثل asyncio :)پارو، aur helper ای که ما پیشفرض توی پارچ داریمش و یک aur helper نوشته شده در راست، یک ابزار شخص ثالثی براش هست به نام paruz که میاد و با fzf همچین چیزی میسازه.
اینطوری خیلی راحت تر میتونید دنبال بسته هاتون با paru بگردید.
نصبش:
به زودی paruz رو توی پارچ به همراه چندتا بسته دیگه به صورت پیشفرض قرار خواهم داد.
اینطوری خیلی راحت تر میتونید دنبال بسته هاتون با paru بگردید.
نصبش:
paru -S paruz
به زودی paruz رو توی پارچ به همراه چندتا بسته دیگه به صورت پیشفرض قرار خواهم داد.
This media is not supported in your browser
VIEW IN TELEGRAM
مثل که vscode ساپورت از چند مانیتور رو روی نسخه بتاش اضافه کرده.
https://github.com/microsoft/vscode/issues/10121
https://github.com/microsoft/vscode/issues/10121
@python4all_pro - Data Cleaning Cheat Sheet in py.pdf
168.9 KB
🔘 پاکسازی داده ها با پایتون
🔻چرا دادههای تمیز بسیار مهم هستند، چه چیزی می تواند باعث خطا شود و چگونه خطا ها را شناسایی، پیشگیری و رفع کنیم تا داده های خود را تمیز نگه داریم. مبارزه با دیتاهای آلوده و دسترسی به دیتاهای تمیز یکی از بزرگترین دغدغه های دیتاساینتیست هاست برای آموزش این موضوع از چیت شیت های پاک سازی داده با پایتون که در کانال منتشر میشه استفاده کنید .
✔️دوتا دوره خوب هم با همین موضوع معرفی میکنم استفاده کنید
1️⃣ آموزش پاک سازی داده با پایتون از یودمی : لینک
2️⃣ آموزش ضروری پاکسازی داده ها در پایتون با زیرنویس فارسی : لینک
Cheat Sheet 1 : #Data_Cleaning
#علم_داده #cheat_sheet #pdf
🔻چرا دادههای تمیز بسیار مهم هستند، چه چیزی می تواند باعث خطا شود و چگونه خطا ها را شناسایی، پیشگیری و رفع کنیم تا داده های خود را تمیز نگه داریم. مبارزه با دیتاهای آلوده و دسترسی به دیتاهای تمیز یکی از بزرگترین دغدغه های دیتاساینتیست هاست برای آموزش این موضوع از چیت شیت های پاک سازی داده با پایتون که در کانال منتشر میشه استفاده کنید .
✔️دوتا دوره خوب هم با همین موضوع معرفی میکنم استفاده کنید
1️⃣ آموزش پاک سازی داده با پایتون از یودمی : لینک
2️⃣ آموزش ضروری پاکسازی داده ها در پایتون با زیرنویس فارسی : لینک
Cheat Sheet 1 : #Data_Cleaning
#علم_داده #cheat_sheet #pdf
@python4all_pro -Data Cleaning and.pdf
3.7 MB
🔘 پاکسازی داده ها با پایتون
🔻چرا دادههای تمیز بسیار مهم هستند، چه چیزی می تواند باعث خطا شود و چگونه خطا ها را شناسایی، پیشگیری و رفع کنیم تا داده های خود را تمیز نگه داریم. مبارزه با دیتاهای آلوده و دسترسی به دیتاهای تمیز یکی از بزرگترین دغدغه های دیتاساینتیست هاست برای آموزش این موضوع از چیت شیت های پاک سازی داده با پایتون که در کانال منتشر میشه استفاده کنید .
✔️ویدیو ها :
1️⃣ آموزش پاک سازی داده با پایتون از یودمی : لینک
2️⃣ آموزش ضروری پاکسازی داده ها در پایتون با زیرنویس فارسی : لینک
چیت شیت ها:
1️⃣ چیت شیت شماره ۱ :https://t.me/pythonlearnme/191
Cheat Sheet 2 : #Data_Cleaning
#علم_داده #cheat_sheet #pdf
🔻چرا دادههای تمیز بسیار مهم هستند، چه چیزی می تواند باعث خطا شود و چگونه خطا ها را شناسایی، پیشگیری و رفع کنیم تا داده های خود را تمیز نگه داریم. مبارزه با دیتاهای آلوده و دسترسی به دیتاهای تمیز یکی از بزرگترین دغدغه های دیتاساینتیست هاست برای آموزش این موضوع از چیت شیت های پاک سازی داده با پایتون که در کانال منتشر میشه استفاده کنید .
✔️ویدیو ها :
1️⃣ آموزش پاک سازی داده با پایتون از یودمی : لینک
2️⃣ آموزش ضروری پاکسازی داده ها در پایتون با زیرنویس فارسی : لینک
چیت شیت ها:
1️⃣ چیت شیت شماره ۱ :https://t.me/pythonlearnme/191
Cheat Sheet 2 : #Data_Cleaning
#علم_داده #cheat_sheet #pdf
🕹 بازی تتریس در ترمینال
بازسازی تتریس الکسی پاژیتنوف با زبان بش.
این نسخه از تتریس، بازسازی بازی تتزیس اورجینال است که به دست Alexey Pajitnov در سال 1985 ساخته شد.
👈 📹 ویدیو تتریس اورجینال
🔸 برای دانلود دستور زیر را اجرا کنید:
🔹سپس:
و از بازی تتریس در ترمینال لذت ببرید.
این بازی هیچ dependency جز خود بش نداره و همهجا بدون اشکال اجرا میشه.
خوندن کد بازی هم جذابیت خودش رو داره و میتونین ببینین چطوری مهرههای تتریس با آرایه ساخته شدن و اینکه کل اسکریپت بدون استفاده از curses داره توی ترمینال گرافیک ایجاد میکنه .
#معرفی #بازی #بش #لینوکس
بازسازی تتریس الکسی پاژیتنوف با زبان بش.
این نسخه از تتریس، بازسازی بازی تتزیس اورجینال است که به دست Alexey Pajitnov در سال 1985 ساخته شد.
👈 📹 ویدیو تتریس اورجینال
🔸 برای دانلود دستور زیر را اجرا کنید:
curl -O -L https://raw.githubusercontent.com/kt97679/tetris/master/tetris.sh
🔹سپس:
chmod +x tetris.sh
./tetris.sh
و از بازی تتریس در ترمینال لذت ببرید.
این بازی هیچ dependency جز خود بش نداره و همهجا بدون اشکال اجرا میشه.
#معرفی #بازی #بش #لینوکس
-اصل Use Pronounceable Names در کلین کد
این اصل میگه که شما باید اسم هایی که برای متغیر هاتون انتخاب میکنید قابل تلفظ باشه اگه نتونید تلفظش کنید نمیتونید در بارش بحث کنید بدون این که صدای احمقانه در بیارید این مهمه چون برنامه نویسی یه فعالیت اجتماعیه
ما برنامه نویسا باید اسم هارو جوری انتخاب کنیم که وقتی در بارش توضیح میدیم راحت باشیم مثلا این دوتا کد رو ببینید اولی اسم های غیر قابل تلفظ داره و دومی اسم های درست درمون
کد زیر :
میتونه با متغیر های بهتر زیر نوشته باشه :
حالا وقتی میخوایم به رفیقمون بگیم بیا یه نگاه به این کد بنداز دیگه راحت تلفظ میکنیم و صدای احمقانه در نمیاریم
این اصل میگه که شما باید اسم هایی که برای متغیر هاتون انتخاب میکنید قابل تلفظ باشه اگه نتونید تلفظش کنید نمیتونید در بارش بحث کنید بدون این که صدای احمقانه در بیارید این مهمه چون برنامه نویسی یه فعالیت اجتماعیه
ما برنامه نویسا باید اسم هارو جوری انتخاب کنیم که وقتی در بارش توضیح میدیم راحت باشیم مثلا این دوتا کد رو ببینید اولی اسم های غیر قابل تلفظ داره و دومی اسم های درست درمون
کد زیر :
class DtaRcd102 {
private Date genymdhms;
private Date modymdhms;
private final String pszqint = "102";
};
میتونه با متغیر های بهتر زیر نوشته باشه :
class Customer {
private Date generationTimestamp;
private Date modificationTimestamp;
private final String recordId = "102";
};
حالا وقتی میخوایم به رفیقمون بگیم بیا یه نگاه به این کد بنداز دیگه راحت تلفظ میکنیم و صدای احمقانه در نمیاریم
Forwarded from DevTwitter | توییت برنامه نویسی
درخت مرکل (Merkle Tree) یا درخت هش Hash Tree
ٰکاربرد:
Git, Blockchain , ...
توضیح:
نوعی ساختمان داده شامل یک درخت که خلاصهٔ اطلاعات یک دادهٔ بزرگتر نگه میدارد و برای تشخیص محتویات
ابزار:
با merkdir میتوانید از دایرکتوری سیستم خودتان Merkle tree بسازید
https://github.com/makew0rld/merkdir
@DevTwitter | <MehrdadLinux/>
ٰکاربرد:
Git, Blockchain , ...
توضیح:
نوعی ساختمان داده شامل یک درخت که خلاصهٔ اطلاعات یک دادهٔ بزرگتر نگه میدارد و برای تشخیص محتویات
ابزار:
با merkdir میتوانید از دایرکتوری سیستم خودتان Merkle tree بسازید
https://github.com/makew0rld/merkdir
@DevTwitter | <MehrdadLinux/>
یک خبر عالی: دیگه نوشتن کد توی Jupyter رو به ChatGPT بسپار
✅ با Jupyter AI به طور مستقیم میتونی کدهات رو با نوشتن prompt مناسب تولید کنی
✅ توی لینک های زیر یاد بگیرین چطور ازش استفاده کنین:
گیت هاب: https://lnkd.in/gKWbZTwR
داکیومنت: https://lnkd.in/gN5zYxtx
✅ با Jupyter AI به طور مستقیم میتونی کدهات رو با نوشتن prompt مناسب تولید کنی
✅ توی لینک های زیر یاد بگیرین چطور ازش استفاده کنین:
گیت هاب: https://lnkd.in/gKWbZTwR
داکیومنت: https://lnkd.in/gN5zYxtx
ایراد کد زیر چیست؟ فکر کنید این تابع قراره یک جایی از سیستم بک اندتون استفاده شه. قراره آدرس یوزر رو از یکی از سرویس های اینترنالتون از طریق پروتکل http بگیره. چه ایرادی میتونید تو این کد پیدا کنید؟
(resp.text)
from httpx import AsyncClient, HTTPError
from some_module import AddressNotFoundError, UserServiceException, UserId
from pydantic import BaseModel
class Address(BaseModel):
location: str
house_num: int
async def get_address(user_id: UserId) -> Address:
client = AsyncClient()
try:
resp = await client.get("http://user_service/v1/user-address", params={"user_id": user_id})
if resp.status_code == 404:
raise AddressNotFoundError(text=resp.text)
return Address(**resp.json())
except Exception as error:
raise UserServiceException
(resp.text)
from error
یکی از بهترین منبع های یادگیری گیت, خوده داکیومنتشه .
https://git-scm.com/book/en/v2
یک از سرفصل هاش submodule هست که واقعا میتونه مفید باشه براتون مخصوصا برای فرانت کارا و کسایی که js میزنن.
It often happens that while working on one project, you need to use another project from within it. Perhaps it’s a library that a third party developed or that you’re developing separately and using in multiple parent projects. A common issue arises in these scenarios: you want to be able to treat the two projects as separate yet still be able to use one from within the other.
https://git-scm.com/book/en/v2/Git-Tools-Submodules
https://git-scm.com/book/en/v2
یک از سرفصل هاش submodule هست که واقعا میتونه مفید باشه براتون مخصوصا برای فرانت کارا و کسایی که js میزنن.
It often happens that while working on one project, you need to use another project from within it. Perhaps it’s a library that a third party developed or that you’re developing separately and using in multiple parent projects. A common issue arises in these scenarios: you want to be able to treat the two projects as separate yet still be able to use one from within the other.
https://git-scm.com/book/en/v2/Git-Tools-Submodules
با سلام و وقت بخیر این گروه به هدف پرسش و پاسخ مسیر راه و رفع اشکال در تمام حوزه های برنامه نویسی ساخته شده و تمامی دوستانی که در حوزه های مختلف برنامه نویسی کار میکنید و دوستان تازه کاری که سعی دارن به طور کلی رفع اشکال های خودشان را انجام بدن میتوانند اشکال های خود راه رفع کنند و از دوستانی که سابقه کار در حوزه های برنامه نویسی را داشته اند تجربه کسب کنند موفق و موید باشید ❤️
https://t.me/+PMg6KSn2PQI1NzFk
https://t.me/+PMg6KSn2PQI1NzFk
Telegram
🧑💻اجتماع برنامه نویسان🧑💻
Deleted Account invites you to join this group on Telegram.
چند تا نکته پرتکرار در مورد رزومه نوشتن:
۱. اولا recruiter ها به طور میانگین ۸-۱۲ ثانیه رو هر رزومه وقت میذارن. واسه همین bold کردن کیوردها خیلی خیلی مهمه. سعی کنین مطالب مهمتر رو همون اول بیارین و در کل کار طرف رو برای فهمیدنش آسونتر کنین
۲. لیست skills بهتره اول آورده شه که لیستیه از تکنولوژی ها و زبان های برنامه نویسی و…
بعدش تو هر کدوم از تجربه های کاری یا حتی پژوهشی، تکنولوژی/زبان برنامه نویسی/مدل ماشین لرنینگ… استفاده شده بهتره bold شه. اینطوری اون مهارت باورپذیرتر میشه و بهش context داده میشه
۳. اعداد خیلی مهمن برای هر تجربه کاری. چیزایی مثل:
تعداد افرادی که تو هر پروژه باهاشون کار کردین و مخصوصاً lead کردین
تعداد افرادی که از تیمهای دیگه باهاشون کار کردین و پوزیشنهاشون
حجم داده ورودی
تعداد کاربرها
مقدار تغییر متریک با انجام اون پروژه
تعداد request در ثانیه،…
۴. برای پوزیشن های کاری، فقط چند تا publication کافیه و واسه بقیه بهتره لینک داده شه به google scholar. وگرنه اهمیت بقیه رزومه تحت تاثیر قرار میگیره. حتی بخش education میتونه پایینتر قرار بگیره و قبلش تجربه کاری و پروژههای مهم رو بیارین
۵. واسه هر پوزیشن سعی کنین رزومه رو یه کم ادیت کنین تا بیشتر به job description شبیه شه. حتی اگه skill جدید نیازه که قبلاً تجربهشو نداشتین، میتونین چند تا پروژه جانبی انجام بدین و به رزومه اضافه کنین. اونطوری کیوردهایی که دنبالشن رو راحتتر در اختیارشون قرار میدین
۶. به همه کسایی که میخوان رزومهشونو بفرستن واسم تا نظرمو بگم، میگم باشه. ولی در عمل اصن فرصتشو نمیکنم یا شاید تنبلیم میاد اما در مجموع نکته خیلی متفاوتی نسبت به چیزایی که اینجا گفتم به ذهنم نمیرسه معمولاً. امیدوارم اینطوری به آدمای بیشتری کمک کنه
۱. اولا recruiter ها به طور میانگین ۸-۱۲ ثانیه رو هر رزومه وقت میذارن. واسه همین bold کردن کیوردها خیلی خیلی مهمه. سعی کنین مطالب مهمتر رو همون اول بیارین و در کل کار طرف رو برای فهمیدنش آسونتر کنین
۲. لیست skills بهتره اول آورده شه که لیستیه از تکنولوژی ها و زبان های برنامه نویسی و…
بعدش تو هر کدوم از تجربه های کاری یا حتی پژوهشی، تکنولوژی/زبان برنامه نویسی/مدل ماشین لرنینگ… استفاده شده بهتره bold شه. اینطوری اون مهارت باورپذیرتر میشه و بهش context داده میشه
۳. اعداد خیلی مهمن برای هر تجربه کاری. چیزایی مثل:
تعداد افرادی که تو هر پروژه باهاشون کار کردین و مخصوصاً lead کردین
تعداد افرادی که از تیمهای دیگه باهاشون کار کردین و پوزیشنهاشون
حجم داده ورودی
تعداد کاربرها
مقدار تغییر متریک با انجام اون پروژه
تعداد request در ثانیه،…
۴. برای پوزیشن های کاری، فقط چند تا publication کافیه و واسه بقیه بهتره لینک داده شه به google scholar. وگرنه اهمیت بقیه رزومه تحت تاثیر قرار میگیره. حتی بخش education میتونه پایینتر قرار بگیره و قبلش تجربه کاری و پروژههای مهم رو بیارین
۵. واسه هر پوزیشن سعی کنین رزومه رو یه کم ادیت کنین تا بیشتر به job description شبیه شه. حتی اگه skill جدید نیازه که قبلاً تجربهشو نداشتین، میتونین چند تا پروژه جانبی انجام بدین و به رزومه اضافه کنین. اونطوری کیوردهایی که دنبالشن رو راحتتر در اختیارشون قرار میدین
۶. به همه کسایی که میخوان رزومهشونو بفرستن واسم تا نظرمو بگم، میگم باشه. ولی در عمل اصن فرصتشو نمیکنم یا شاید تنبلیم میاد اما در مجموع نکته خیلی متفاوتی نسبت به چیزایی که اینجا گفتم به ذهنم نمیرسه معمولاً. امیدوارم اینطوری به آدمای بیشتری کمک کنه
من راجب
این کد رو یکی از اعضا فرستاده (درحال code review این کد رو دیده)
یکی از دلایلی که
رو استفاده میکنیم این هست که دیگه
باقی مشکلات رو شما بگید (به اکثر موارد قبلاً اشاره شده توی کانال)
repr
, str
, ... صحبت کردم.این کد رو یکی از اعضا فرستاده (درحال code review این کد رو دیده)
@dataclassی مورد رو من بگم و بعد سکوت کنم :
class CasbinRuleEntity:
id: typing.Optional[int] = None
ptype: typing.Optional[str] = None
v0: typing.Optional[str] = None
v1: typing.Optional[str] = None
v2: typing.Optional[str] = None
v3: typing.Optional[str] = None
v4: typing.Optional[str] = None
v5: typing.Optional[str] = None
def __str__(self):
arr = [self.ptype]
for v in (self.v0, self.v1, self.v2, self.v3, self.v4, self.v5):
if v is None:
break
arr.append(v)
return ', '.join(arr)
def __repr__(self):
return '<CasbinRule {}: "{}">'.format(self.id, str(self))
یکی از دلایلی که
@dataclass
رو استفاده میکنیم این هست که دیگه
repr
بدرد نخور ننویسیم.باقی مشکلات رو شما بگید (به اکثر موارد قبلاً اشاره شده توی کانال)
🧑💻PythonDev🧑💻
من راجب repr, str , ... صحبت کردم. این کد رو یکی از اعضا فرستاده (درحال code review این کد رو دیده) @dataclass class CasbinRuleEntity: id: typing.Optional[int] = None ptype: typing.Optional[str] = None v0: typing.Optional[str] = None v1:…
دوستان به موارد زیادی اشاره کردند اما گفتم یکبار هم خودم همهی آن چیزی که توی کد ریویو انجام میدم رو بگم :
۱- وقتی کلاس یا تابع تعریف میکنید که خودش یا اجزا تشکیل دهندهاش مشخص نیست حتما باید داکیومنت یا کامنت داشته باشه
بدترین اسامی هست که میشه انتخاب کرد؛ چون برنامه نویس داره فرض میکنه که همهی افرادی که کد رو میخونند بیزینس رو بخوبی میشناسند.
۲- استفاده از
۳- از
۴- حالا که نوشته شده
۵- داخل
عدم استفاده از
عدم استفاده از
فرمت اشتباه؛ خروجی
۶- خورد
من حتی به این حالت هم فکر کردم که چون تعداد متغییرها زیاد بوده برنامهنویس خواسته از یک جایی به بعد
تقریبا ۲۰ خط کد بود و ۳۰ خط ایراد.
۱- وقتی کلاس یا تابع تعریف میکنید که خودش یا اجزا تشکیل دهندهاش مشخص نیست حتما باید داکیومنت یا کامنت داشته باشه
v0, v1, v2 , ...
بدترین اسامی هست که میشه انتخاب کرد؛ چون برنامه نویس داره فرض میکنه که همهی افرادی که کد رو میخونند بیزینس رو بخوبی میشناسند.
۲- استفاده از
typing optional
در اینجا درست نیست مخصوصا که برای همهی موارد تکرار شده و به همهی موارد دیفالت None
داده شده؛ حتی اگر همین کد رو بخوایم نگه داریم این راهکارها بهتر خواهد بود :v0: str | None
v0: typing.Union[str, None]
۳- از
dataclass
هیچ استفادهای نشده (frozen, ordering, slot ,
....) حتی از ویژگیهای حالت سادهترش هم استفاده نشده؛ مثل پیاده سازی methods که
یعنی repr و s
tr نیازی نبود نوشته بشه.۴- حالا که نوشته شده
repr
در
انتهای خروجی به str(self)
رو داره و این یعنی برنامه نویس سواد نوشتن repr درس
ت رو نداشته و چون توی حلقه بینهایت میوفته مجبور شده که str رو
هم پیادهسازی کنه۵- داخل
repr همه
چیز پر از ایراد هست (تمام موارد رو قبلا بررسی کردیم تو کانال) :عدم استفاده از
qualname
, هاردکد کردن اسم کلاسعدم استفاده از
r!
جهت نمایش درست تایپهای داخلیفرمت اشتباه؛ خروجی
repr رو
برای ساخت مجدد آبجکت از کلاس نمیشه استفاده کرد.۶- خورد
str کلا
سوال هست؛ نوشتاری که تمیز نیست؛ هدفش مشخص نیست و ....من حتی به این حالت هم فکر کردم که چون تعداد متغییرها زیاد بوده برنامهنویس خواسته از یک جایی به بعد
...
نشون بده مثل کاری که numpy , ....
میکنند؛ که اگر هدف هم این بوده پیاده سازی اشتباهی انجام داده و با یک جستجوی ساده حتی میتونسته به راهکار درست برسه reprlib builtin module
تقریبا ۲۰ خط کد بود و ۳۰ خط ایراد.
✔️ استیبل بودن یا نبودن یک الگوریتم مرتب سازی
یکی از دسته بندی های موجود برای الگوریتم هایsort کردن، فاکتور stable بودن یا نبودن هست. به طور خلاصه به الگوریتمی میگن stable که:
موقع sort کردن یک لیست، اگه ۲ تا آیتم مساوی هم بودن، دقیقا به همون ترتیبی که توی لیست اولیه بودن، توی لیست مرتب شده هم ظاهر بشن.
فرض کنید به شما میگن لیست زیر رو بر اساس: اول نمره و بعد درصورت یکسان بودن نمره ها، بر اساس حروف الفبا مرتب کنید. منتاها این لیستی که به شما میدن خودش بر اساس حروف الفبا مرتب شده هست:
lst = [
("Ashkan",17),
("Bahar",18),
("Sorena",17)
]
یک راه مرسوم اینه که به این روش sort رو انجام بدیم:
lst.sort(key=lambda x: (x[1], x[0]))
کاملا درسته و هیچ اشکالی نداره. بیشتر میخواستیم درباره موضوع پست صحبت کنیم.
آیا میتونیم فقط بیایم بر اساس آیتم دوم sort ش کنیم؟ این که خود لیست بر اساس حروف الفبا مرتب شده آیا کمکی میکنه؟ یعنی:
lst.sort(key=lambda x: x[1])
اگه بدونیم الگوریتمی که استفاده شده stable هست بله میتونیم و گارانتی هست که آیتم های مساوی به همون ترتیب در خروجی قرار میگیرن، و چون در حال حاضر بر اساس حروف الفبا مرتب شده هستن، اون افرادی که نمره ی برابر دارن اتوماتیک بر اساس حروف الفبا هم مرتب هستن.
خروجی هردو:
[
('Ashkan', 17),
('Sorena', 17),
('Bahar', 18)
]
پایتون از Tim Sort استفاده میکنه و stable هست.
چند تا از الگوریتم های مرتب سازی استیبل:
• Insertion Sort
• Merge Sort
• Bubble Sort
• Tim Sort
و نقطهی مقابلشون:
• Heap Sort
• Selection Sort
• Quick Sort
یکی از دسته بندی های موجود برای الگوریتم هایsort کردن، فاکتور stable بودن یا نبودن هست. به طور خلاصه به الگوریتمی میگن stable که:
موقع sort کردن یک لیست، اگه ۲ تا آیتم مساوی هم بودن، دقیقا به همون ترتیبی که توی لیست اولیه بودن، توی لیست مرتب شده هم ظاهر بشن.
فرض کنید به شما میگن لیست زیر رو بر اساس: اول نمره و بعد درصورت یکسان بودن نمره ها، بر اساس حروف الفبا مرتب کنید. منتاها این لیستی که به شما میدن خودش بر اساس حروف الفبا مرتب شده هست:
lst = [
("Ashkan",17),
("Bahar",18),
("Sorena",17)
]
یک راه مرسوم اینه که به این روش sort رو انجام بدیم:
lst.sort(key=lambda x: (x[1], x[0]))
کاملا درسته و هیچ اشکالی نداره. بیشتر میخواستیم درباره موضوع پست صحبت کنیم.
آیا میتونیم فقط بیایم بر اساس آیتم دوم sort ش کنیم؟ این که خود لیست بر اساس حروف الفبا مرتب شده آیا کمکی میکنه؟ یعنی:
lst.sort(key=lambda x: x[1])
اگه بدونیم الگوریتمی که استفاده شده stable هست بله میتونیم و گارانتی هست که آیتم های مساوی به همون ترتیب در خروجی قرار میگیرن، و چون در حال حاضر بر اساس حروف الفبا مرتب شده هستن، اون افرادی که نمره ی برابر دارن اتوماتیک بر اساس حروف الفبا هم مرتب هستن.
خروجی هردو:
[
('Ashkan', 17),
('Sorena', 17),
('Bahar', 18)
]
پایتون از Tim Sort استفاده میکنه و stable هست.
چند تا از الگوریتم های مرتب سازی استیبل:
• Insertion Sort
• Merge Sort
• Bubble Sort
• Tim Sort
و نقطهی مقابلشون:
• Heap Sort
• Selection Sort
• Quick Sort