جنگولرن
3.82K subscribers
287 photos
74 videos
31 files
557 links
آموزش Django و بستگان
Download Telegram
اگر شما می‌خواستین stackoverflow رو طراحی کنید چه کار میکردید؟ احتمالا جواب خیلیا با اون حجم کاربر microservice باشه.
ولی جواب اینه که خیر. یه monolith روی چند تا سروره و تمام!

توی یه قسمت از خبرنامه‌ی bytebytego می‌تونید در موردش بخونید:
https://blog.bytebytego.com/p/ep27-stack-overflow-architecture

در مورد اینکه چطوری به این performance می‌رسن، این صفحه از stack exchange هم جالبه:
https://stackexchange.com/performance
👍2
مطلبی در مورد index ها در PostgreSQL از کانال @djangoex

در پستگرس (PostgreSQL) چند نوع مختلف شاخص یا ایندکس (Index) وجود دارد که هر کدام برای کاربردهای خاصی طراحی شده اند. در زیر به معرفی و بررسی آنها می‌پردازم:

یک. B-tree: این نوع شاخص، پیش فرض برای هر نوع داده‌ها می‌باشد. سریعترین ایندکس برای عملیات مقایسه‌ای مانند =, <, <=, >, >= می‌باشد.

دو. Hash: این نوع از شاخص فقط برای عملیات مساوی (=) سریع است و برای سایر عملیات‌های مقایسه‌ای کارآیی مناسبی ندارد.

سه. GiST (Generalized Search Tree): این شاخص پشتیبانی می کند از و نسخه سازگاری بسیار پذیر است که از حوزه های داده و عملیات مقایسه متنوعی پشتیبانی می کند.

چهار. SP-GiST (Space-Partitioned Generalized Search Tree): این نوع شاخص فراهم می کند برای انواع مختلفی از بازیابی های داده، به خصوص زمانی که داده ها یک ساختار فضایی شیر نمی کند.

پنج. GIN (Generalized Inverted Index): این شاخص مناسب برای داده‌هایی است که مقادیر چندگانه در یک سطر دارند، مانند آرایه‌ها و JSON.

شش. BRIN (Block Range INdex): این شاخص مناسب برای جداول بزرگ است که سطرهای آنها به طور فیزیکی بر اساس برخی مقادیر مرتب شده‌اند.

برای مطالعه بیشتر حول این موضوع میتوانید به مستندات PostgreSQL مراجعه نمایید.
2
Forwarded from ProgrammingSchool (Python)
قسمت اول: قراردادهای پایتون

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

In a series of posts, the conventions that must be followed when coding in Python are introduced. These conventions are taken from popular Python projects and standard libraries and evolve over time.

این قراردادها خوانایی کد را بالا می‌برند. خوانایی کد، مهم‌تر از نوشتن کد است. هر برنامه‌نویسی که کار توسعه نرم‌افزار را انجام می‌دهد باید با این قراردادها آشنایی کامل داشته باشد. در پست بعد در مورد Hanging indent ها صحبت می‌کنیم.

These conventions improve code readability. Code readability is more important than code writing. Every programmer who does software development should be familiar with these contracts. we will talk about hanging indents in the next post.

#آموزش_پایتون
#قراردادهای_پایتون

آدرس کانال:
@Programmingschool2
سایت آموزشی:
https://programmingschool.ir
👍3
Forwarded from ProgrammingSchool (Python)
قسمت دوم: قراردادهای پایتون
تورفتگی‌های Hanging Indent

خطوطی که بیش از ۷۹ کاراکتر دارند باید به صورت عمودی نوشته شوند. در هنگام نوشتن عمودی، باید پیوستگی خط حفظ شود. یکی از راه‌های حفظ پیوستگی، استفاده از پرانتز یا براکت است. تراز شدن خطوط با استفاده از Hanging indent انجام می‌شود. تورفتگی‌ Hanging یک سبک نوشتاری است که در آن تمام خطوط یک پاراگراف به جز خط اول تورفتگی دارند. در پایتون، این اصطلاح برای توصیف سبکی استفاده می‌شود که در آن پرانتز آغازین یک عبارت پرانتزدار، آخرین کاراکتر خط اول است و خطوط بعدی تا پرانتز بسته، تورفتگی دارند.

Lines longer than 79 characters must be written vertically. Line continuity must be maintained when writing vertically. One of the ways to maintain continuity is to use parentheses or brucet. Alignment of lines is done using Hanging indent. Hanging indentation is a writing style in which all lines of a paragraph are indented except for the first line. In Python, this term is used to describe a style in which the opening parenthesis of a parenthesized expression is the last character of the first line, and subsequent lines are indented up to the closing parenthesis.


هنگام استفاده از تورفتگی‌های Hanging باید در نظر گرفت که خط اول نباید هیچ آرگومانی داشته باشد. همچنین می‌توان از تورفتگی‌های بیشتر برای تشخیص واضح خطوط مذکور استفاده شود.

When using hanging indents, note that the first line should not have any arguments. Also, more indentations can be used to clearly distinguish the mentioned lines.

#آموزش_پایتون
#قراردادهای_پایتون

آدرس کانال:
@Programmingschool2
سایت آموزشی:
https://programmingschool.ir
گروه پرسش و پاسخ:
https://t.iss.one/programmingschool_group
👍2
از Linkedin آقای arash hosseini #مهندسی_سیستم لینک در نظرات پست
مهندسی سیستم بخش ششم:

پذیرش سیستم :
میزان موفقیت هر سیستم دست ساخته بشر و ماموریتش در شاخص های پذیرش ذیل نهفته است :
· آیا بازار برای پذیرش سیستم جدید آمادگی دارد ؟ یک نیاز عملیاتی به پنجره ای از موقعیت های جدید
· درک کاربر از ابزارهای عملیاتی، سازگاری و در دسترس بودن
· توانایی سیستم در انجام و به ثمر رساندن اهداف کاربر – اثر بخشی سیستم
· بازگشت سرمایه برای منابع وابسته به عملیات و نگهداری سیستم – به صرفه بودن
بیشتر افراد پذیرش سیستم را از دریچه رضایت زمینه کاری مشتری می بینند. مهندسین غالبا اندازه گیری این موضوع را به بعد از ارائه و توزیع سیستم در بازار محول می کنند. بر اساس چیزی که سازمان از نظرسنجی های پس از تحویل می آموزد، مهندسین ممکن است سیستم یا محصول را اصلاح کنند اگر :
· کاربر موقعیتی جدید برای رفع کمبودها، طی یک قرارداد توسعه به آنها ارائه نماید. البته کمبودهایی که در قرارداد اولیه در نظر گرفته نشده باشد.
· پیش بینی های سود بلندمدت سرمایه گذاری داخلی را ارزشمندتر نماید.
شما به عنوان یک مهندس سیستم باید نیازهای عملیاتی کاربر را قبل از توسعه و نظر سنجی درک نمائید، شما باید درک کنید که :
· کاربر قرار است چگونه از سیستم یا محصول شما استفاده نماید ؟
· چه معیارهایی برای موفقیت باید اعمال شود ؟
· پیامد شکست کاربر و بوجود آمدن شاخه های جدید از درجاتی از موفقیت چیست ؟
اگر توسعه دهندگان سیستم شاخص موفقیت برای پذیرش سیستم از طرف کاربر را درک ننمایند، بهترین طراحی نیز بیهوده خواهد بود، در نتیجه این موضوع یکی از مفاهیم پایه در مهندسی سیستم خواهد بود. شاخص های پذیرش یاد شده اگر چه از نظر روانی برابر به نظر می رسند، بندرت به صورت همزمان در حالت مطلوب قرار می گیرند. معیارهای ذهنی - یعنی درک از ابزارهای عملیاتی، مناسب بودن و دسترس پذیری، اغلب معیارهای عینی موفقیت سیستم (اثربخشی . به صرفه بودن) را مبهم می نماید.
· فاکتورهای نگاه ذهنی ، حس و درک در جامعه همتایان سیستم یا منبع سرمایه گذاری قالبا پذیرش موفقیت سیستم از دید کاربر را تا اندازه ای تیره تار می نماید.
· در مقابل، کاربر برای همان دلایل ذهنی ممکن است موفقیت عینی یک سیستم را زیر سوال ببرد.
در نهایت، برخی از رویدادها بررسی واقعیت را ممکن می سازد. یک تصمیم برای ادامه کار با یک سیستم ممکن است منجر به ایجاد نیاز به یک بروزرسانی برای تصحیح کمبودها، حذف تدریجی یک سیستم یا جایگزینی آن با یک سیستم جدید گردد. یک آن
ابزار عملیاتی، مناسب، در دسترس و موثر پیش ران اطمینان از وجود مهندسی سیستم به عنوان یکی از اجزای اصلی توسعه کلان از ایده تا ارائه نهایی می‌باشد. این فاکتورها به مانند شعار در میان بازاریاب ها مرسوم هستند و اغلب اندازه گیری آنها برای پیاده سازی بسیار دشوار می باشد. به طور معمول پیاده سازی سیستم نیاز به متخصصینی دارد که میزان قابل توجهی از تمرکز عمر کاری خود را بر اندازه گیری و ارائه این اطلاعات به نحوی که واقعی و قابل فهم برای تصمیم گیران کلیدی باشد، صرف کرده اند.
چالش های کلیدی توسعه سیستم های قابل پذیرش از طرف کاربران :
موفقیت و درجه پذیرش سیستم، محصول یا خدمت غالبا به کمک پاسخ به مجموعه ای سوالات که با آنالیز قبل از توسعه و با بازخورد و دریافت نتایج بعد از توسعه اندازه گیری می شود، اندازه گیری می شود. سوالاتی شامل موارد ذیل :
ادامه در کامنت
🔥3
بجای کد نویس بودن، برنامه نویس باشید!

بعضی از مطالبی که پست میکنم. شاید اینطور به نظر بیاد که ربطی به کانال جنگولرن ندارن
اما قرار نیست ما کدنویس باشیم. قراره برنامه نویس باشیم و حتی فراتر از برنامه نویس!!!

مطلب زیر رو بخونید. تفاوت کد نویسی و برنامه نویسی رو تقریبا گفته:
https://roocket.ir/articles/programming-or-coding
👍10
شروع دوره طراحی الگوریتم از کانال @BenDevelop
توصیه میکنم پیگیر این دوره باشید. نه به خاطر مدرسش (که البته واقعا کارش درسته) به خاطر اینکه یاد گرفتن طراحی الگوریتم میتونه مارو به سمت حرفه ای شدن توی برنامه نویسی سوق بده.
وقتی طراحی الگوریتم و ساختمان داده بلدی. خیلی بهتر میتونی کد بهینه بنویسی که سرعت اجرای بالایی هم داشته باشه و منابع زیادی هم مصرف نکنه.

اینم اولین ویدیو معرفی دوره الگوریتم و ساختمان داده که صحبتش رو کرده بودیم
تو این ویدیو دوره رو معرفی می‌کنم و توضیح می‌دم که دوره برای چه کسایی هستش و به چه ترتیبی باید ببینیدش

https://youtu.be/kclXvoKsEEY

@BenDevelop
👍3🔥2
Forwarded from ProgrammingSchool (Python)
قسمت سوم: تورفتگی‌های بخش شرطی if

زمانی که بخش شرطی یک عبارت if طولانی باشد لازم است در چند خط نوشته شود. در این حالت، نوشتن کلمه کلیدی و پرانتز باز در خط اول و بقیه شروط در سایر خطوط ایده جالبی نیست(مشابه Hanging Indent). زیرا باعث تداخل کدهای شرط if با کدهای بلوک آن شود.

When the conditional part of an if-statement is long, it requires to be written on multiple lines. In this case, it isn't an interesting idea to write the keyword if and open parenthesis in the first line and the rest of the conditions in the other lines (similar to Hanging Indent). Because it makes the code less readable.

در این حالت PEP هیچ ایده صریحی ندارد. برخی از شکل های نوشتاری قابل قبول عبارتند از:

In this case, PEP has no clear idea. Some acceptable written forms are:

۱- سایر خطوط مربوط به بخش شرطی، به صورت همتراز با خطوط بلاک if نوشته شود.

1- Other lines related to the conditional section should be alignment to the lines of the if block.

۲- بین خطوط بخش شرطی و دستورهای بلوک if یک خط کامنت قرار می‌دهند.

2- A comment line is placed between the lines of the conditional section and the if block commands

۳- تورفتگی های بخش شرطی، بیشتر از دستورات بلوک if است.

3- The indents of the conditional section are more than the if block commands.

#آموزش_پایتون
#قراردادهای_پایتون

آدرس کانال:
@Programmingschool2
سایت آموزشی:
https://programmingschool.ir
گروه پرسش و پاسخ:
https://t.iss.one/programmingschool_group
👍1
Forwarded from ProgrammingSchool (Python)
قسمت سوم: تورفتگی‌های بخش شرطی if

در مثال بالا، سه فرم صحیح عبارت if با شرط طولانی را مشاهده می‌کنید.

In the example above, you see the three correct forms of the if statement with a long condition.

Please write clean code.🙏🙏

#آموزش_پایتون
#قراردادهای_پایتون

آدرس کانال:
@Programmingschool2
سایت آموزشی:
https://programmingschool.ir
گروه پرسش و پاسخ:
https://t.iss.one/programmingschool_group
👍3
جنگولرن
مطلب مفیدی درباره Logging از کانال @PyHints یک دوستی دیروز راجب لاگ نویسی توی پایتون سوال داشت من به اینصورت براش توضیح دادم گفتم شاید مفید باشه : Python logging components : 1- Loggers وضعیت لاگ؛ همیشه لازم هست. نشون میده هر دسته از لاگ رو چطور باید…
پیاده سازی logging در جنگو

توی جنگو، logging یک ابزاره که بهتون کمک می‌کنه تا پیام‌های مختلف رو ثبت و مدیریت کنید.
این پیام‌ها می‌تونن شامل پیام‌های عملیاتی، اطلاعاتی و خطاها باشن. با استفاده از logging می‌تونید اطلاعات مربوط به برنامه‌تون رو به صورت منظم ثبت و بررسی کنید.

تنظیمات logging توی settings.py قرار میگیره. این تنظیمات شامل مواردی مثل جایی که پیام‌های لاگ ذخیره بشن و چطور برچسب‌گذاری بشن، هستن.

توی کدهای جنگو می‌تونید از logging استفاده کنید. اول باید یه logger با یه نام دلخواه ایجاد کنید. بعد می‌تونید با استفاده از اون logger پیام‌های مختلف رو ثبت کنید. مثلا:

import logging

logger = logging.getLogger('my_logger')

logger.debug('DEBUG')
logger.info('INFORMATION')
logger.warning('WARNING')
logger.error('ERROR')
logger.critical('CRITICAL')

لینک داکیومنت جنگو:
https://docs.djangoproject.com/en/4.2/topics/logging/
👍2🤔1
جنگولرن
ترکیب Middleware های جنگو با logging ✔️ میتونیم با استفاده از میدلور ها و logging اطلاعات مفیدی رو لاگ کنیم. مثلا همه request و response هارو لاگ کنیم. این مثال: https://zeroes.dev/p/django-middleware-to-log-requests/ ✔️ یا همه Exception هایی که رخ میده…
لاگ کردن چه استفاده ای میتونه داشته باشه؟

یکی از استفاده هاش که میتونه دیباگ کردن باشه.
اما استفاده مهم ترش میتونه مونیتورینگ باشه.

ریپو زیر رو ببینید عنوانش گویای ماجراست
Monitoring Django applications with Grafana and Kibana using Prometheus and Elasticsearch


https://github.com/gonzalo123/django-logs
👍4
پست مفیدی از کانال @ManiFoldsPython در مورد جاب آفر گرفتن از شرکت های خارجی
بقیه نکات در کامنت ها

مواردی که به نظر من یک بک اند کار برای کار تو شرکت های مدرن خارجی و گرفتن جاب آفر داخلشون باید بلد باشه, طبق تجربه این چند وقتم داخل مصاحبه ها و جاب هایی که دیدم:

1. آشنایی با گیت
2. تست نویسی
3. آشنایی با github action برای نوشتن فایل work flow yaml
4. درک عمیق تر از پایتون (خوندن کتابی مثل fluent python یا python cook book)
تسلط به پترن دیزاین ها
5. آشنایی با paradigms های مختلف برنامه نویسی
6. الگوریتم
7. تسلط روی SQL
8. آشنایی با MySQL یا PostgreSQL.
9. آشنایی با داکر و داکر کامپوز
10. آشنایی با مفاهیم Event driven architecture, SOA, microservice و Monolithic
11. تسلط رو یک فریم ورک microservice friendly مثل FastAPI یا Flask
12. آشنایی با یک فریم ورک Monolithic مثل جنگو میتونه مزیت خوبی باشه.
13. آشنایی با یک سرویس کلاد (AWS/Azure/GCP) در حد نیاز بک اند. معمولا certificate های مشخصی دارن که میتونید راجبشون تحقیق کنید و تو اون مسیری که مربوط به بک اند دولوپر میشه برین.
14. آشنایی با دیتابیس های کلاد مثل amazon rds
15. آشنایی با serverless و نمونش داخل کلاد مثل AWS Lambda
16. آشنایی با k8s در حد نوشتن فایل yaml سرویستون
17. آشنایی با یک ابزار IAC مثل terraform
(از بین ترافورم یا k8s و داکر, معمولا رو یکیش تمرکز میکنن شرکتا. و تو اغلب آگهی ها هم دیدم وزن بیشتر سمت داکر و k8s بوده تا ترافورم)


@ManiFoldsPython
👍4
Forwarded from Meysam
فقط برای ریسرچ.
اگر دنبال موضوع، استاد، دانشجو برای پوزیشن خاص، نویسنده همکار، سوال در زمینه ژورنال و کنفرانس و ... هستید عضو بشید.

هرگونه بی احترامی باعث ریمو‌میشه.
پروژه درسی سفارش ندید و نگیرید باعث ریمو‌ شدنتان میشود.

با تشکر.

لینک گروه:
https://t.iss.one/researcher_people
👍1
HashMaps به بیان ساده:
قرار هست ببینیم associative array چیه، hashmap چیه، چه ارتباطی به dictionary داره، ویژگی هاشون چیه، hash collision چیه، چطور برطرف میشن، نمونه خیلی سادش رو پیاده سازی کنیم و در انتها یه نمونه کامل هم ببینیم ازش.

خب... زمانی که ما یک سری دیتا داریم که به هم مرتبط هستن میتونیم اون ها رو توی یه collection نگهداری کنیم مثلا array. اطلاعاتی مثل تمام نمرات دانش آموزان یک کلاس:
grades = [17, 19, 18, ...]
و با ایندکس های عددی بهشون دسترسی پیدا کنیم:
grades[2]
خیلی هم سریع هستن array ها تو دسترسی چون مستقیم میریم سراغ همون نمره ای که نیاز داریم.
مشکل کجاست؟
مشکل اینه که برای ما سخته حفظ کنیم کدوم ایندکس برای کدوم شخص بوده و ترجیح میدیم که اگه نمره ی شخصی رو میخوایم به جای اینکه یه عدد بی معنی بدیم، اسمش رو بدیم و نمرش رو بگیریم:
grades["ali"]
راه حل چیه؟
اینکه اسمش رو(که بهش میگیم کلید) متصل یا مربوط یا "associate" بکنیم به نمرش.
چطوری؟ مثلا:
grades = [("reza", 17), ("sara", 19), ("ali", 18)]
و بعد هم اینجوری میگیریم:
def get_grade(person_name):
for name, grade in grades:
if name == person_name:
return grade

print(get_grade("ali"))
خیلی بهتر و راحت تر شد الان...
چیزی که ما بالا ساختیم یک پیاده سازی (بد) از associative array بود. چون associate کردیم یک کلید رو به مقدارش. associative array یک abstract هست و میتونه به شکل های مختلف پیاده سازی بشه.

خب... فقط یه مشکلی هست الان:
قبلا که با ایندکس میگرفتیم صاف میرفتیم سراغ خودش، الان مجبوریم که iterate کنیم روشون و دونه دونه بگردیم تا برسیم به اونی که میخوایم. کنده!! (شما مثال های این پست رو با ۱۰۰۰ تا داده مثلا تصور کنید)

راه حل چیه؟
اینکه بیایم "یه جوری" این اسم ها رو map کنیم به ایندکس های عددی تا دوباره بتونیم صاف بریم سراغ اونی که میخوایم و سرعت بهتر بگیریم.

چطور اینکارو بکنیم؟
مثلا بیایم یک فانکشن بنویسیم که از کلیدها عدد تولید کنیم به این صورت که اعداد اسکی متناظر با هر حرف از کلیدمون رو باهم جمع کنیم. یعنی برای sara داریم:
s: 115
a: 97
r: 114
a: 97
در نتیجه:
"sara" # -> 115 + 97 + 114 + 97 -> 423
این میشه فانکشنش:
def hash_func(string):
return sum(map(ord, string))
حالا یه لیست بسازیم که ۵ تا جای خالی داره:
grades = [None, None, None, None, None]

خب حالا الان عددی که از هش کردن(پس یه هش فانکشن ساده بود اون) کلید sara به دست آوردیم و چطور map کنیم به یکی از ایندکس های لیستمون؟ ما که ۴۲۳ تا slot نداریم...
باقی ماندش رو با طول لیستمون حساب کنیم!
اینطوری مطمئن هستیم که داخل اون رنجی که میخوایم هست. پس:
423 % 5 -> 3
کافیه sara و نمرش رو توی ایندکس شماره ۳ ذخیره کنیم:
grades = [None, None, None, ("sara", 19), None]
اگه همین کار رو برای باقی هم بکنیم همچین چیزی میشه:
grades = [
("ali", 18),
None,
None,
("sara", 19),
("reza", 17),
]
(تو پرانتز حواسمون هست که ترتیبش عوض شد...)

الان خوب شد. هر کدوم از نمره هارو بخوایم بگیریم اول اون کلید رو hash میکنیم بعد باقی ماندش رو حساب میکنیم میشه ایندکس مورد نظر. دیگه iteration ای در کار نیست و به time complexity عه O(1) رسیدیم. الان get_grade عه ما اینطوری شد:

def hash_func(string):
return sum(map(ord, string))

def get_grade(person_name):
hash_value = hash_func(person_name)
idx = hash_value % 5
return grades[idx][1]

print(get_grade("reza"))

موقع insert کردن هم دقیقا برعکس همین شکل عمل میکنیم یعنی ابتدا هش میکنیم بعد باقیمانده میگیریم بعد که فهمیدیم کدوم slot برای اون کلید میشه میذاریمش اونجا. درواقع هر چیزی که برای get کردن میگیم برعکسش برای set کردن میشه.

خب ما الان تونستیم associative array رو با کمک hashmap پیاده سازی کنیم :) بریم ادامش...

حالا اگه اسم یکی دیگه از دانشجو ها aras بود چی؟
(پست بعدی)

پست ۱ از ۳
👍2
چجوری aras رو اضافه کنیم به grades ؟ چون aras از همون حروفی که sara داره تشکیل شده با هش فانکشنی که ما نوشتیم دوباره بهمون ۴۲۳ میده و اگه باقی مانده بگیریم میشه ۳ یا درواقع همون ایندکسی که برای سارا اختصاص داده شده.
مشکل بوجود اومد... به این مشکل میگن hash collision یا تداخل هش ها!

هش فانکشنی که انتخاب کردیم شاید زیاد جالب نبود چون درواقع به ازای تمام جای گشت های یک کلمه همون هش رو بهمون میده.

هش فانکشن خوب توی hashmap ها دو تا ویژگی داره:
۱- باید محاسباتش سبک باشه. چون دائما داره برای همه ی کلید ها حساب میشه.
۲- "سعی کنه" مقدار های یونیک تولید کنه تا به hash collision بر نخوریم.

بیایم کمی تغییرش بدیم: علاوه بر اینکه از عدد اسکیشون استفاده میکنیم، بیایم اون عدد رو در جایگاهی که داره(حرف چندمه) ضرب هم بکنیم به این شکل:
def hash_func(string):
hash_value = 0
for i, char in enumerate(string, start=1):
hash_value += ord(char) * i
return hash_value

الان هش collision رو بر طرف کردیم:
for name in ("ali", "sara", "reza", "aras"):
hash_value = hash_func(name)
print(f"{name}: {hash_value} : {hash_value % 5}")
خروجیش میشه:
ali:  628  : 3
sara: 1039 : 4
reza: 1070 : 0
aras: 1076 : 1
ولی همونطور که حدس میزنید باز هم با کلید های مختلف ما به hash collision بر میخوریم... مثلا جای aras بذارید nima ...
چه کنیم؟ بیایم یه هش فانکشن معقول داشته باشیم که سعی کنه با سرعت بالا hash value رو محاسبه کنه (چیزی که الان داریم) ولی اگه collision پیش اومد رفعش کنیم! چطور؟

روش اول، separate chaining :
تو این روش میگه به جای اینکه ما بیایم slot ها رو خالی بذاریم (None) ، بیایم به جاش از لیست خالی استفاده کنیم! هر موقع hash collision داشتیم میایم اضافش میکنیم به لیست.

یعنی اگه ۴ تا دانش آموزش ما باشن: ali, sara, reza, nima
با هش فانکشن جدیدی که نوشتیم slot های ما به این صورت میشن:
grades = [
[("reza", 17), ("nima", 20)],
[],
[],
[("ali", 18)],
[("sara", 19)],
]
مشکل حل شد. الان با اینکه وقتی نمره ی نیما رو بخوایم باید قبلش یه رضا رو هم چک کنیم ولی خیلی جلو افتادیم نسبت به اینکه بخوایم همه رو چک کنیم! یعنی کلی کلید رو محاسبه نمیکنیم فقط اون چندتایی که collision داشتن سرچ میشن. و خب باقی کلید ها که collision نداشتن مستقیم پیدا میشن.

اگه دقت کنیم میبینیم هرچی hash collision بیشتر داشته باشیم به رفتار خطی بیشتر نزدیک میشیم.
این روش اول بود که پیاده سازی خیلی ساده ای هم داره. یه مشکلی ریزی داریم اینجا. یه سری فضای خالی الان توی slot های ما بوجود اومده. آیا میتونیم بیایم از این فضاها استفاده کنیم؟


روش دوم، open addressing:
شرایطی و در نظر بگیرید که الان reza و ali و sara ذخیره شدن و ما میخوایم nima رو اضافه کنیم:
grades = [
("reza", 17),
None,
None,
("ali", 18),
("sara", 19),
]
میایم nima رو هش میکنیم ایندکس و پیدا میکنیم میبینیم میشه صفر. و نگاه میکنیم میبینیم پر هست! میایم یه sequence ای تولید میکنیم به اسم probing sequence. به طوری که از همون اون ایندکسی که محاسبه کردیم شروع میشه(اینجا شد صفر برای نیما) و یه دور میزنه:
0 -> 1 -> 2 -> 3 -> 4
اگه برای ali میخواستیم probing sequence چی میشد؟
3 -> 4 -> 0 -> 1 -> 2
و به همین ترتیب میریم جلو تا به جای خالی برسیم. الان برای نیما ایندکس بعدی میشه ۱. خالی هست؟ بله. پس میذاریمش اونجا و تبدیل میشه به:
grades = [
("reza", 17),
("nima", 20),
None,
("ali", 18),
("sara", 19),
]
ما ۳ شکل probe sequence داریم:
1- linear probing
2- quadratic probing
3- double hashing

کاری که بالا کردیم linear probing بود. چون نمیخوام بیشتر از این طولانی بشه دوتای دیگه رو اینجا نمیگم(پیاده سازیش رو در انتها گذاشتم) ولی حدس زدنش سادس. مثلا تو دومی به جای اینکه دونه دونه بره بالا ، با توان های ۲ میره بالا (کمک میکنه که توده ای از کلید ها رو یک جای hash table مون نداشته باشیم پخش بشن) و آخری میگه یه هش دیگه(هش دوم) انجام بدیم برای پیدا کردن ایندکس بعدی!

اینا هر کدوم مزایا و معایبی دارن که میشه کلی دربارشون بحث کرد که کدوم کجا چرا بهتره.

پست تموم شد ولی یه سری نکته های تکمیلی باقی موند:
(پست بعدی و آخر)

پست ۲ از ۳
نکته ۱:
دیکشنری توی پایتون نمونه از associative array هست که با hashtable یا hashmap پیاده سازی شده.

نکته ۲:
این پیاده سازی از hashmap چیزی هست که همین الان تو خیلی از زبان ها برای دیکشنری، set ها توی پایتون و برای دیکشنری ها تا قبل از ورژن ۳.۶ توی پایتون استفاده میشده.
به طور کلی hashmap ها ترتیب رو حفظ نمیکنن، همونطور که دیدید ولی از پایتون ۳.۶ به بعد آقای Raymond Hettinger یه پیاده سازی جدیدی برای دیکشنری ها انجام داد به اسم raymond dict. کلیت همینه ولی یه مقدار فرق داره با چیزی که دیدیم که هم کم حجم تره هم باعث میشه ترتیب رو حفظ کنن. اگه علاقه داشتید میتونم بعدا پیاده سازی دیکشنری های جدید پایتون رو هم بگم.

نکته ۳: توی separate chaining میشه به جای لیست از linked list یا binary search tree هم استفاده کرد که باز هم هر کدوم معایب و مزایای خودشون رو دارن.

نکته ۴:
خیلی از نکات گفته نشد به دلیل اینکه نمیخواستم بیشتر از این طولانی بشه. از جمله:
- پایتون علاوه بر key و value خود هش‌ها رو هم نگه داره میکنه. چرا اینکارو میکنه؟
- این hash table عه ما به یه حدی که برسه نیاز داره تا resize بشه تا پرفورمنسش رو حفظ کنه. اگه از یه حدی بیشتر پر باشه تعداد دفعاتی که collision میگیریم بیشتر میشه و دیکشنری یا ست ما کند تر میشه.
- اگه یه کلیدی و delete کردیم تکلیف hashtable چی میشه؟ چطور باید هندل بشه؟

من همه ی انواع implementation هایی که اسمشون اومد رو به صورت کامل پیاده سازی کردم و نکاتی که وقت نشد رو توش گنجوندم. میتونید به عنوان رفرنس بهش یه نگاه بندازید:

* Open Addressing:
- Linear Probing
- Quadratic Probing
- Double Hashing Probing
* Separate Chaining
- With Dynamic Array
- With Linked List
- With Binary Search Tree

https://github.com/amirsoroush/Python_Hashmaps

پست ۳ از ۳

🖊 @AmirSoroushh
1
Forwarded from ProgrammingSchool (Python)
قسمت چهارم: ساختارهای چندخطی

پرانتز، براکت یا آکولادهای پایانی در ساختارهای چندخطی مانند لیست‌ها، دیکشنری ها و ...

The closing parantese, brace or brucet in multiline structures such as lists, dictionaries, etc:

۱- می‌تواند همتراز با اولین کاراکتر غیرسفید از آخرین خط این ساختارها نوشته می‌شود.

1- It can be written in line with the first non-white character from the last line of these structures

۲- در ابتدای آخرین خط نوشته شود.
2- It should be written at the beginning of the last line.

مثال های بالا این دو حالت را نشان می‌دهد:
The above examples show these two states:

#آموزش_پایتون
#قراردادهای_پایتون

آدرس کانال:
@Programmingschool2
سایت آموزشی:
https://programmingschool.ir
گروه پرسش و پاسخ:
https://t.iss.one/programmingschool_group
👍1