<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های مهدی نظری</title>
        <link>https://virgool.io/feed/@mehdinazari</link>
        <description>یک دولوپر خسته که پایتون را دوست می دارد.</description>
        <language>fa</language>
        <pubDate>2026-04-15 08:56:34</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/77146/avatar/gMAovK.png?height=120&amp;width=120</url>
            <title>مهدی نظری</title>
            <link>https://virgool.io/@mehdinazari</link>
        </image>

                    <item>
                <title>سیر تا پیاز caching</title>
                <link>https://virgool.io/@mehdinazari/%D8%B3%DB%8C%D8%B1-%D8%AA%D8%A7-%D9%BE%DB%8C%D8%A7%D8%B2-caching-chif693nmzpt</link>
                <description>کش کردن یعنی داده هایی که از قبل درخواست شده اند و امکان درخواست مجدد آن وجود دارد یا داده هایی که می توان تا دسترسی به داده از سرور به کاربر نمایش داده شوند در محلی ذخیره شوند تا سرعت افزایش یابد و سیستم بهینه تر شود. به طور خلاصه caching تکنیکی برای ذخیره کردن موقت داده ها در حافظه است. به صورت کلی به دو صورت سخت افزاری و نرم افزاری انجام می شود. انواع کش کردن نرم افزاری در back-end با ذخیره اطلاعات در حافظه کش (معمولا RAM) و در front-end به صورت ذخیره اطلاعات در حافظه مرورگر امکان پذیر است، و کش کردن سخت افراری کش DNS سرور ها و Cache server ها.کاربرد اصلی کش کردن زمانی است که برنامه درگیر محاسبات سنگینی است یا بنا به دلایل دیگر دریافت پاسخ زمان بر باشد، در این گونه مواقع تا زمان دریافت داده های جدید، داده های کش شده را در اختیار کاربر قرار می دهیم. همچنین در بعضی مواقع ریکوئست های تکراری در سیستم زیاد است یا ریکوئست هایی وجود دارد که پاسخ آن ها معمولا با تغییرات زیادی همراه نیستند، در این مواقع caching موجب می شود تا تنها برای داده هایی که نیاز است request ها به سمت سرور ارسال گردند و سایر داده ها از حافظه کش در اختیار کاربر قرار می گیرد. البته داده های کش با استفاده از روش های مختلف دائما به روز می شوند. در عملیات caching داده ها یا با موفقیت cache می شوند (اصطلاحا heat اتفاق افتاده) و یا با شکست مواجه می شوند (miss). هدف اصلی caching پایین آوردن Response Time درخواست‌های کاربران و پایین آوردن بار ترافیکی روی سیستم و دیتابیس است.تا اینجا به بررسی caching و مزایای آن در سیستم پرداختیم ولی caching می تواند مشکلاتی هم ایجاد کند: حتی در صورتی که caching به صورت صحیح پیاده سازی شده باشد مراحل اضافه ای جهت کش کردن اطلاعات به سیستم افزوده می شود. در صورت پیاده سازی غیر صحیح این امر کاملا مشهود خواهد بود.از دیگر مشکلاتی که در caching وجود دارد این است که ممکن است اطلاعات کش اطلاعات قدیمی باشد زیرا ممکن است اطلاعات با موفقیت کش نشده باشد یا در هنگام برگرداندن پاسخ از کش داده در دیتابیس تغییر کرده باشد.از آنجایی که فضای cache محدود است و ما نیاز دائمی به داده های کش شده نداریم، روش هایی برای حذف داده های قدیمی تر و جایگزین کردنشان با داده های جدید و مدیریت داده ها وجود دارد:روش LRU (Least Recently Used)در این روش داده های بیشتر استفاده شده به بالای حافظه منتقل شده و داده های کمتر استفاده شده حذف می شود.این روش از رایج ترین روش ها در caching است. در این روش هرگاه داده ای درخواست شود به بالای کش منتقل می شود، به این ترتیب الگوریتم می تواند داده هایی که کمتر از آن ها استفاده شده است را با مشاهده انتهای کش شناسایی کند. این الگوریتم فرض بر این است که هرچه تعداد درخواست ها برای یک داده بیشتر باشد باید بیشتر در فضای کش باقی بماند.روش LFU (Least Frequently Used)در این روش یک شمارنده تعداد استفاده از داده ها را محاسبه کرده و داده هایی که کمترین استفاده از آن ها شده باشند حذف می شوند.روش MFU (Most Recently Used)در این روش داده هایی که بیشتر استفاده شده باشند حذف می شوند. این روش زمانی که داده های قدیمی تر با اهمیت تر هستند کاربرد دارد.انواع الگوریتم های cashingروش Cache-Asideاین روش را می توان یکی از متداول‌ترین روش‌های caching دانست. در مواقعی که درخواست کش کردن بیشتر از درخواست خواندن اطلاعات است. در این روش اگر داده ها در cache موجود باشند در اختیار کاربر قرار داده می شود و در صورت که موجود نباشد داده از سرور درخواست می شود و برای کاربر ارسال می شود، سپس داده در cache ذخیره خواهد شد.روش Read-Through Cacheدر این روش دیتابیس و کش به صورت in-line هستند و درخواست‌ها به cache ارسال می شود. کش با داده های دیتابیس sync می شود، اگر داده در کش وجود نداشته باشد، از دیتابیس درخواست می شود و کش آپدیت می کنیم، سپس داده در اختیار کاربر قرار می گیرد. تفاوت این روش با روش قبل در این است که برنامه همیشه با cache در ارتباط است.روش Write-Through Cache مانند روش قبل برنامه همیشه با cache در ارتباط است. در این حالت اطلاعات ابتدا در cache ذخیره می شوند و دیتابیس با کش sync می شود. در این حالت احتمال cache miss به حداقل می رسد.روش Write Backاین روش مشابه روش قبل است با این تفاوت که ذخیره اطلاعات از cache به database در لحظه صورت نمی گیرد و مثلا در بازه های زمانی خاص صورت می گیرد. در این روش اگر داده های cache از بین برود دیگر به آنها دسترسی نداریم بنابراین این روش پر ریسک محسوب می شود.روش Write Aroundدر این روش اطلاعات روی دیتابیس ذخیره می شود و در زمان درخواست، فقط اطلاعات درخواست شده روی کش قرار می گیرد.کش کردن در pythonدر پایتون با استفاده از دکوراتور lru_cache@ که در پکیج functools وجود دارد می توان عملیات caching را انجام داد. پکیج functools پکیجی higher-order است، به این معنی که یا ورودی آن تابع است و یا یک تابع را به عنوان خروجی باز می گرداند.این دکوراتور از یک دیکشنری ذخیره می کند که شامل argument ها و نتیجه تابع است. بنا براین argument ها باید قابلیت hash شدن را داشته باشند تا دکوراتور بتواند کار خود را انجام دهد.مثال زیر را بدون در نظر گرفتن کار که انجام می دهد در نظر بگیرید:from timeit import repeat

def steps_to(stair):
    if stair == 1:
        return 1
    elif stair == 2:
        return 2
    elif stair == 3:
        return 4
    else:
        return (
            steps_to(stair - 3) + steps_to(stair - 2) + steps_to(stair - 1)        )setup_code = &amp;quotfrom __main__ import steps_to&amp;quot
stmt = &amp;quotsteps_to(30)&amp;quot
times = repeat(setup=setup_code, stmt=stmt, repeat=3, number=10)
print(f&amp;quotMinimum execution time: {min(times)}&amp;quot)خروجی کد بالا به صورت زیر خواهد بود:Minimum execution time: 29.684728438001912حال دکوراتور lru_cache@ را به منظور کش کردن نتیجه به کد بالا اضافه می کنیم:from functools import lru_cache
from timeit import repeat

def steps_to(stair):
.
.
.و همانطور که مشاهده می کنیم نتیجه به شکل قابل توجهی سریع تر خواهد بودMinimum execution time: 1.2620002962648869e-06با استفاده از print(steps_to.cache_info())می توان جزئیات نربوط به کش کردن کد بالا را مشاهده کرد که ۸۲ بار عملیات کش شدن با موفقیت انجام شده و ۳۰ شکست هم در این عملیات مشاهده می شود:CacheInfo(hits=82, misses=30, maxsize=128, currsize=30)کش کردن با استفاده از Redisردیس (redis) به عنوان یک message queue یا message broker شناخته می شود که داده ها را به صورت key-value در خود ذخیره می کند. از مزایای redis سرعت، سادگی در ساختار، ttl و کاربردی بودن آن است.ردیس ابزاری قدرتمند جهت کش کردن یک سیستم به شمار می آید که با در اختیار قرار دادن data type های مختلف بنا به نیازمندی و معماری سیستم می تواند انتخاب مناسبی برای caching باشد.انواع Data Type ها در Redis:کلید(key): برای ذخیره داده به صورت key: value کاربرد دارد.هش (Hsah): برای ذخیره داده به صورت hash_name field1: value1, hash_name field2: value و... کاربرد دارد.لیست (List):برای ذخیره داده به صورت list_name: valu1, value2, ... value(n) کاربرد دارد.برای نصب ردیس در ubuntu دستور زیر را در terminal وارد می کنیم:sudo apt install redis-serverو برای اتصال به redis در terminal دستور زیر را وارد می کنیم:redis-serverبرای اطمینان از اتصال به ردیس دستور ping را وارد می کنیم و در صورتی که PONG در خروجی برگردانده شود دسترسی به redis به درستی صورت گرفته است.کلید ها (KEYS)همانطور که قبلا هم اشاره شد redis پایگاه داده ای مبتنی بر کلید-مقدار (key-value) است. برای تعریف یک  key و مقدار دادن به آن از دستور زیر استفاده می کنیم:SET KEY [KEY_NAME] [VALUE]برای مقدار دادن به یک کلید در صورتی که وجود نداشته باشد از دستور زیر استفاده می کنیم:SET KEY [KEY_NAME] [VALUE]برای مقدار دادن به چند کلید همزمان از دستور زیر استفاده می کنیم:MSET KEY [KEY_NAME1] [VALUE1] [KEY_NAME2] [VALUE2] ... [KEY_NAMEn] [VALUEn]نکته: در صورتی که یکی از کلیدها از قبل وجود داشته باشد هیچ کدام از مقادیر ثبت نخواهند شد.برای دسترسی به همه کلید ها از دستور زیر استفاده می کنیم:KEYS *برای دسترسی به مقادیر یک کلید از دستور زیر استفاده می کنیم:GET [KEY_NAME]اگر بخواهیم به چند کلید را همزمان GET کنیم از دستور زیر استفاده می کنیم:MGET [KEY_NAME] [KEY_NAME1] ... [KEY_NAMEn]برای تغییر نام یک کلید از دستور زیر استفاده می کنیم:RENAME [KEY_NAME] [NEW_KEY_NAME]برای حذف یک کلید از دستور زیر استفاده می کنیم:DEL [KEY_NAME]برای بررسی وجود داشتن یک کلید در کلید از دستور زیر استفاده می کنیم:EXISTS [KEY_NAME]برای ایجاد موقتی یک کلید به صورت ثانیه از دستور زیر استفاده می کنیم (n ثانیه):SET [KEY_NAME] [VALUE]
EXPIRE [KEY_NAME] #n(second)برای مشاهده میزان باقی مانده از طول عمر رشته از دستور زیر استفاده می کنیم:TTL [KEY_NAME]نکته: در صورت expire شدن کلید مقدار 2- برگردانده می شود.در صورتی که بخواهیم دستور EXPIRE را خنثی کنیم از دستور زیر استفاده می کنیم:PERSIST [KEY_NAME]نکته: در صورتی که expire روی کلیدی اعمال نشده باشد و یا دستور persist را بعد از expire  روی یک کلید اعمال کنیم مقدار برگشتی از دستور &#x27;[TTL &#x27;[KEY_NAM برابر با 1- خواهد بود.دستورات مربوط به هش ها:برای ایجاد یک مقدار در هش از دستور زیر استفاده می کنیم:HSET [HASH_NAME] [FIELD] [VALUE]دریافت مقادیر فیلد یک hashHGET [HASH_NAME] [FIELD_NAME]دریافت همه مقادیر یک hashHGETALL [HASH_NAME]کلید های یک hashHKEYS [HASH_NAME]ذخیره دسته ای در یک hashHMSET [HASH_NAME1] [FIELD1] [VALUE1] [HASH_NAME2] [FIELD2] [VALUE2] ... [HASH_NAMEn] [FIELDn] [VALUEn]دستورات مربوط به لیست ها:برای قرار دادن مقادیر در ابتدای لیست از LPUSH و برای قراردادن از انتهای لیست از RPUSH استفاده می کنیمLPUSH [LIST_NAME] [VALUE1] [VALUE2] ... [VALUEN] RPUSH [LIST_NAME] [VALUE1] [VALUE2] ... [VALUEN] برای وارد کردن مقادیر در لیست در صورت وجود لیست از دستو زیر استفاده می کنیم: LPUSHX [LIST_NAME] [VALUE1] [VALUE2] ... [VALUEN] 
RPUSHX [LIST_NAME] [VALUE1] [VALUE2] ... [VALUEN]برای دسترسی به آخرین عنصر لیست از دستور زیر استفاده می کنیم.LPOP [LIST_NAME] [VALUE2] ... [VALUEN] برای دسترسی به اولین عنصر لیست از دستور زیر استفاده می کنیم.RPOP [LIST_NAME] نکته: در صورتی که بخواهیم به آخرین عنصر لیست اشاره کنیم از 1- استفاده می کنیم.برای حذف چند عنصر لیست از دستور زیر استفاده می کنیم:LREM [LIST_NAME] counter [VALUE]</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Thu, 26 Aug 2021 17:50:10 +0430</pubDate>
            </item>
                    <item>
                <title>iterable vs iterators</title>
                <link>https://virgool.io/@mehdinazari/iterable-and-iterators-gal9miwnyofm</link>
                <description>در پایتون Iterator ها یک Object هستند که متد __iter__ روی آن ها پیاده سازی می شود تا بتوان روی یک iterable عمل iterate را انجام داد. در حقیقت __iter__ یا متد ()iter یک iterable دریافت کرده و یک iterator را بر می گرداند (متد ()iter آبجکت iterator را initialize می کند). لیست ها، تاپل ها، دیکشنری ها، مجموعه ها و رشته ها به عنوان iterable شناخته می شوند و می توان با استفاده از for روی آن ها عمل iterate را انجام داد.هر Iterator باید متد های __iter__ و __next__ را پیاده سازی کند.__iter__این متد آبجکت iterator را initialization می کند و یک iterable دریافت کرده و یک iterator برمیگرداند.__next__ این متد یک iterator دریافت کرده و به مقدار بعدی در iterator اشاره می کند و اگر مقدار بعدی وجود نداشت (به انتهای iterator رسیدیم) StopIteration را raise می کند.حال با یک مثال تعاریف بالا را بررسی می کنیم:values = [1, 2, 3, 4, 5]
iterator_values = iter(values)
print(next(iterator_values))
print(next(iterator_values))
print(next(iterator_values))

# output
&gt;&gt;&gt; 1
&gt;&gt;&gt; 2
&gt;&gt;&gt; 3در مثال بالا ابتدا یک iterable تعریف کردیم (values) و سپس با استفاده از متد iter آن را به یک iterator تبدیل کردیم و در نهایت با استفاده از متد next روی آن عملیات iterate را انجام دادیم (به عنصر بعدی دسترسی پیدا کردیم).برای مشاهده تفاوت iterable و iterator مثال بالا را اندکی تغییر می دهیم تا با خطای زیر مواجه شویم:values = [1,2,3,4,5]
next(values)
&gt;&gt;&gt;TypeError: &#039;list&#039; object is not an iteratorهمانطور که مشاهده می کنید متد next انتظار یک iterator دارد تا روی آن iterate کند اما لیستی که به آن پاس داده شده این قابلیت را ندارد، چون یک iterable است.مثال) ایجاد یک custom iteratorمثال زیر یک iterator را پیاده سازی می کند که یک عدد دریافت کرده و  در صورتی که از 10 کوچکتر نباشد از 10 تا ورودی را پرینت می کند:class Test:
    def __init__(self, limit):
        self.limit = limit

    def __iter__(self):
        self.x = 10
        return self

    def __next__(self):
        x = self.x
        if x &gt; self.limit:
            raise StopIteration
        self.x = x + 1
        return x
for i in Test(15):
    print(i)for i in Test(5):
    print(i)خروجی10
11
12
13
14
15مثال) ایجاد یک custom iteratorدر مثال زیر یک iterator که کار متد range در for را انجام می دهد پیاده سازی می کنیم. تنها توضیح درباره این مثال اینکه برای اینکه بتوان روی یک object عملیات iterate را پیاده سازی کرد باید دو متد __iter__ و __next__ را پیاده سازی کرد.class Range:
    def __init__(self, start, end, step=1):
        self.start = start
        self.end = end
        self.step = step
    def __iter__(self):
        return self        def __next__(self):
        if self.start &lt; self.end:
            current = self.start
            self.start += self.step
            return current        raise StopIteration                r = Range(10, 20, 3)
for i in r:
    print(i)

# output
&gt;&gt;&gt; 10
&gt;&gt;&gt; 13
&gt;&gt;&gt; 16
&gt;&gt;&gt; 19کتابخانه itertoolsیک کتابخانه پایتونی است که توابع مختلفی برای کار کردن روی iterator ها در اختیار برنامه نویسان قرار می دهد. این ماژول به عنوان ابزاری سریع و استفاده حداقلی از حافظه (memory-efficient) کار می کند.در زیر برخی از مهمترین متد های این کتابخانه را مرور می کنیم:count(start, step):برای تولیدiterator بی نهایت که از start شروع می شود و به تعداد step حرکت می کند. اگر step پاس نداده باشد به طور پیش فرض 1 در نظر گرفته می شود.import itertools

for i in itertools.count(5, 5):
    if i == 35:
        break
    else:
        print(i, end =&amp;quot &amp;quot)
خروجی5 10 15 20 25 30cycle(iterable):این متد عبارات داخل پرانتز را به صورت چرخه تکرار شونده بر می گرداندimport itertools 
count = 0for i in itertools.cycle(&#039;AB&#039;): 
	if count &gt; 7: 
		break
	else: 
		print(i, end = &amp;quot &amp;quot) 
		count += 1خروجیA B A B A B A Brepeat(val, num):این متد val را به تعداد num بار تکرار می کند. خروجی این متد یک لیست است.import itertoolsprint (&amp;quotPrinting the numbers repeatedly : &amp;quot)
print (list(itertools.repeat(25, 4)))خروجیPrinting the numbers repeatedly : 
[25, 25, 25, 25]</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Fri, 20 Aug 2021 00:14:56 +0430</pubDate>
            </item>
                    <item>
                <title>آشنایی با generator ها در پایتون</title>
                <link>https://virgool.io/@mehdinazari/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-generator-%D9%87%D8%A7-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-rm5kal1r1ins</link>
                <description>جنراتور ها (generator) کاملا شبیه توابع عادی در پایتون هستند با این تفاوت که generator ها از yield به جای return استفاده می کنند. تفاوت yield و return در این است که در توابع عادی وقتی interpreter به return می رسد جواب را برمی گرداند و از برنامه خارج می شود ولی در yield جواب برگشت داده می شود ولی از تابع خارج نمی شویم و برنامه به کار خود ادامه می دهد. کار اصلی yield کنترل جریان تابع generator است. زمانی که از یک generator یا generator expression استفاده می کنیم یک iterator که generator نامیده می شود را بر می گرداند. زمانی که interpreter در برنامه به yield بر می خورد، برنامه به حال تعلیق در می آید، state آن ذخیره شده و مقدار تابع yield می شود برعکس return که جریان تابع به طور کامل متوقف شده و مقدار return می شود.در مواقعی که قرار است با یک مجموعه داده بزرگ کار کنیم، یا یک پردازش پیچیده داشته باشیم که هر بار که فراخوانی می شود که باید state خود را نگه دارد و موارد دیگر، generator ها کارکرد فوق العاده خود را نشان می دهند. در حقیقت می توان گفت generator ها می توانند state قبلی خود را حفظ  کنند. جنراتور ها توابع خاصی در پایتون هستند که یک lazy iterator را برمی گردانند. lazy iterator که به آن call-by-need نیز گفته می شود یک استراتژی ارزیابی است که ارزیابی یک عبارت را تا زمان نیاز به مقدار آن به تأخیر می اندازد (ارزیابی غیر سختگیرانه) و همچنین از ارزیابی های مکرر (به اشتراک گذاری) جلوگیری می کند. به اشتراک گذاری می تواند باعث کاهش زمان اجرای برخی از توابع توسط یک عامل نمایشی نسبت به سایر استراتژی های ارزیابی غیر سختگیرانه شود. lazy iterator مانند لیست ها قابلیت iterate شدن را دارند ولی بر خلاف لیست ها قابلیت ذخیره در memory را ندارند.یکی از کاربرد های generator ها کار کردن با data set های سنگین است. مثال زیر شمارش تعداد ردیف های یک فایل csv را نشان می دهد:def csv_reader(file_name):
    file = open(file_name)
    result = file.read().split(&amp;quot\n&amp;quot)
    return resultدر مثال فوق تابع open همه محتویات فایل را به یکباره لود میکند و یک iterator در اختیار ما قرار می دهد که می توان روی آن iterate کرد. حال اگر فایل ارسال شده به تابع csv_reader بزرگتر از سایز مموری آزاد باشد چه اتفاقی می افتد؟ بله MemoryErrorحال مثال بالا را به صورت زیر پیاده سازی می کنیم که def csv_reader(file_name):
    for row in open(file_name, &amp;quotr&amp;quot):
        yield rowدر مثال بالا روی هر سطر iterate می کنیم و به جای return کردن نتیجه آن را yield میکنیم. مثال بالا را با generator comprehension هم می توان پیاده سازی کرد. generator comprehension شبیه list expression است با این تفاوت که به جای [ ] از ( ) استفاده می کنیم. با استفاده از generator comprehension می توان سریع تر و راحت تر generator تعریف کرد.برتری دیگر این روش این است که زمانی که از generator comprehension استفاده می کنیم سربار کمتری روی حافظه خواهیم داشت.کد زیر و مثال بالا معادل همدیگر هستند:csv_gen = (row for row in open(file_name))همانگونه که قبلا اشاره کردیم generator ها در بهینه سازی memory فوق العاده عمل می کنند. مثال زیر مشخص می کند حجم آبجکت generator در مقابل list حدودا 700 برابر کوچکتر است.&gt;&gt;&gt; import sys
&gt;&gt;&gt; nums_squared_lc = [i * 2 for i in range(10000)]
&gt;&gt;&gt; sys.getsizeof(nums_squared_lc)
87624
&gt;&gt;&gt; nums_squared_gc = (i ** 2 for i in range(10000))
&gt;&gt;&gt; print(sys.getsizeof(nums_squared_gc))
120نکته: در مواردی که حجم لیست از حجم memory خیلی کوچکتر باشد list comprehension در مقایسه با generator comprehension سریع تر عمل می کند.کاربرد دیگر generator ها استفاده در برنامه هایی با دنباله بی نهایت است:def infinite_sequence():
    num = 0
    while True:
        yield num
        num += 1

for i in infinite_sequence():
     print(i, end=&amp;quot &amp;quot)خروجی کد بالا به صورت زیر خواهد بود و تا زمانی keyboard interrupt که رخ ندهد ادامه خواهد داشت:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39 40 41 42
[...]
6157818 6157819 6157820 6157821 6157822 6157823 6157824 6157825 6157826 6157827
6157828 6157829 6157830 6157831 6157832 6157833 6157834 6157835 6157836 6157837
6157838 6157839 6157840 6157841 6157842
KeyboardInterrupt
Traceback (most recent call last):
  File &amp;quot&lt;stdin&gt;&amp;quot, line 2, in &lt;module&gt;برنامه فوق را با استفاده از ()next پیاده سازی کرد. از آنجایی که تابع next روی iterator ها قابل اجراست می توان به این مساله پی برد که خروجی generator ها iterator است. &gt;&gt;&gt; gen = infinite_sequence()
&gt;&gt;&gt; next(gen)
0
&gt;&gt;&gt; next(gen)
1
&gt;&gt;&gt; next(gen)
2
&gt;&gt;&gt; next(gen)
3</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Sat, 24 Jul 2021 21:44:39 +0430</pubDate>
            </item>
                    <item>
                <title>مفاهیم concurrency (در پایتون)</title>
                <link>https://virgool.io/Whitenoise/%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-concurrency-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-eelrxsl1ihw2</link>
                <description>به طور کلی برنامه نویسی به دو روش انجام می شود: Synchronous و Asynchronous. در Synchronous پیش از شروع یک کار باید منتظر ماند که کار قبلی به پایان برسد. در Asynchronous کار ها را به صورت همزمان اجرا می کنیم، یعنی می  توان قبل از پایان کار به سراغ کار دیگری رفت.پیش از ادامه صحبت نیاز است تا با تعاریف و اصطلاحاتی آشنا شویم:ترد (Thread): کوچکترین واحد پردازشی است که می توان در یک سیستم عامل اجرا کرد. از یک شمارنده، stack و مجموعه ای از register ها تشکیل شده است. به عبارت ساده Thread مجموعه ای از چندین دستورالعمل در یک برنامه است که می تواند به صورت مستقل از کدهای دیگر اجرا شود. استفاده از thread به اجرای همزمان task ها کمک می کند. اجرای thread ها و process ها از یک سیستم عامل به سیستم عامل دیگر متفاوت است اما در بیشتر موارد، یک thread در داخل یک process قرار دارد و در واقع thread بخشی از process است. چندین thread می توانند در یک process وجود داشته و منابعی مانند حافظه را  به اشتراک بگذارند، در حالی که process های مختلف این منابع را به اشتراک نمی گذارند. thread ها اساسا process هایی هستند که در یک memory context اجرا می شوند.یک thread شامل اطلاعات در یک Thread Control Block (TCB) است:Thread Identifier:  یک شناسه منحصر به فرد (TID)Stack pointer: یک اشاره گر که به محل stack ترد Program counter: آدرس دستوری که در حال حاضر توسط رشته اجرا می شود را ذخیره می کند.Thread state: وضعیت thread را مشخص می کند و یکی از حالت های رو به رو را می پذیرد:  ready, waiting, start, done.Thread’s register set:رجیسترهایی که برای محاسبات به رشته اختصاص داده شده اند.Parent process Pointer:یک اشاره گر به پروسسی که ترد در آن اجرا می شود (PCB).فرآیند (Process) یک instance از برنامه کامپیوتری است که در حال اجرا است که شامل  کد برنامه و مجموعه فعالیت های آن است. بسته به سیستم عامل process ممکن است از چندین thread تشکیل شده باشد که همزمان  دستورالعمل ها را اجرا می کند. هر process مجموعه کاملی از متغیرهای خاص خود را دارد. در آغاز برنامه ها بصورت فایلهایی بر روی هارد قرار دارند. برای اجرا شدن آنها، این فایلها از هارد به RAM منتقل می شوند و کتابخانه های مورد نیاز درون آن Load شده و سپس برنامه اجرا می گردد. در یک تعریف کلی میتوان گفت Process یک برنامه اجرا شده در سیستم عامل می باشد که خود از واحدی کوچکتر به نام Thread تشکیل شده که کوچکترین واحد پردازشی در سیستم عامل می باشد.وظیفه (Task) مجموعه ای از دستورالعمل های برنامه است که در حافظه بارگیری می شوند.تفاوت های Thread و Processپراسس ها مستقل هستند به گونه ای که ‌PID مختص به خود را دارند در صورتی که وجود thread ها وابسته به process است و زیرمجموعه ای از آن ها به حساب می آیند.پراسس توسط CPU کنترل میشه، ولی Thread توسط Process کنترل میشه.می توان process ها را یک Task به حساب آورد ولی هر thread یک Light wight process است.هر Process حافظه اختصاصی (Separate memory) خودش رو داره، ولی Thread ها از حافظه اشتراکی  (Shared memory) و سایر منابع مشترک موجود در process استفاده می کنند.در برنامه نویسی Synchronous یا همروند یک task تا زمانی که اجرای آن به پایان نرسیده پردازنده را در اختیار task دیگری قرار نمی دهد. Synchronous این اطمینان را به ما می‌دهد که تداخلی میان کار thread ها بوجود نخواهد آمد. مثلاً زمانی که یک thread در حال ویرایش و یا ایجاد یک فایل است، سایر thread ها امکان دسترسی به آن فایل را نداشته و باید تا پایان کار thread منتظر بماند. در مقابل، در برنامه نویسی Asynchronous یا غیر همروند می توان task های مختلف را بدون انتظار برای به پایان رسیدن task قبلی انجام داد. این کار توسط روش های مختلف و با مفهومی به نام Concurrency صورت می گیرد.همزمانی (Concurrency):امکان اجرای چندین task را به طور هم‌زمان به توسعه‌دهندگان می دهد. با استفاده از Concurrency می‌توانیم برنامهٔ خود را به چندین بخش مختلف که می‌توانند بدون نوبت اجرا شوند، تقسیم کنیم. همزمانی با روش های asyncio, parallelism, multiprocessing و threading پیاده سازی می شود.در همزمانی  ممکن است اجرای task در نقطه ای متوقف شده و پردازنده در اختیار task دیگری قرار بگیرد. در این زمان پردازنده state آن task را ذخیره می کند و از سرگیری اجرای task از state ذخیره شده انجام می گیرد.در پایتون، concurrency با روش های مختلفی صورت میگیرد (thread, task, process) اما در سطح بالا، همه آنها به دنباله ای از دستورالعمل ها اشاره می کنند که به ترتیب اجرا می شوند.به طور کلی مشکلاتی که همزمانی را پیش روی برنامه نویس قرار می گذارد به دو دسته تقسیم می شوند: I/O-bounding و CPU-bounding. مشکلات I/O-bounding از آنجا که باید منتظر ورودی یا خروجی باشد باعث کند شدن برنامه می شود مانند اتصال شبکه ، هارد دیسک یا چاپگر. راه حل برای افزایش سرعت در این موارد شامل همپوشانی زمان های انتظار برای این دستگاه ها است. در این موارد threading و asyncio گزینه های پیش رو خواهند بود.در مقابل بخش هایی از برنامه هستند که کار پردازش سنگین را انجام می دهند مانند محاسبات سنگین، این بخش ها بخش زیادی از پردازش CPU را به خود مشغول می کنند. در این گونه موارد multiprocessing گزینه مناسبی است. از آنجا که multiprocessing از هسته های مختلف CPU و یا از چندین CPU برای اجرا استفاده می کند گزینه مناسبی برای  برای رفع CPU-bounding است.تشخیص درست اینکه مشکل اصلی برنامه I/O ست یا قدرت پردازش بسیار مهم است و بر اساس آن از گزینه های در دست استفاده می کنیم چون همانگونه که گفته شد ممکن است با انتخاب اشتباه کمکی به افزایش سرعت صورت نگیرد.مثال زیر اجرای یک برنامه synchronous است که در ادامه به روش های گوناگون آن را بازنویسی می کنیم:import requests
import time


def download_site(url, session):
    with session.get(url) as response:
        print(f&amp;quotRead {len(response.content)} from {url}&amp;quot)


def download_all_sites(sites):
    with requests.Session() as session:
        for url in sites:
            download_site(url, session)


if __name__ == &amp;quot__main__&amp;quot:
    sites = [
        &amp;quothttps://www.jython.org&amp;quot,
        &amp;quothttp://olympus.realpython.org/dice&amp;quot,
    ] * 80
    start_time = time.time()
    download_all_sites(sites)
    duration = time.time() - start_time
    print(f&amp;quotDownloaded {len(sites)} in {duration} seconds&amp;quot)در مثال بالا یک حلقه for آدرسی را به متد download_site ارسال می کند و در آن یک request  از نوع get به آن آدرس زده می شود و محتوای آن را دریافت می کند.مشکل برنامه های synchronous همواره کند بودن آنهاست ولی کدها تمیز تر و ساده تر هستند و دیباگ آنها آسان تر است. بنا براین تا مجبور به استفاده از asynchronous نشده ایم به سراغ آن نخواهیم رفت.خروجی کد بالا در سیستم منDownloaded 160 in 38.94426465034485 secondsروش Multi Threadingدر multi threading هر thread می تواند شامل مجموعه رجیستر و متغیرهای محلی خود باشد یا همه thread ها  متغیرهای سراسری  را به اشتراک بگذارند.با استفاده از threading می توان در برنامه اجراهای جداگانه داشت، بنابراین می توان از آن برای اجرای همزمان task ها استفاده کرد. همانگونه که گفته شد هر process حداقل از یک thread تشکیل شده است که به آن Main thread گفته می شود و از آن به عنوان واحد اجرایی برای خود استفاده می کند. در واقع task بدون thread از دید سیستم عامل دلیلی برای ادامه کار ندارد. چیزی که درباره thread ها اهمیت دارد این است که بهتر است در process های IO مورد استفاده قرار بگیرند.و حالا مثال پیاده سازی شده با threading:import concurrent.futures
import requests
import threading
import time


thread_local = threading.local()


def get_session():
    if not hasattr(thread_local, &amp;quotsession&amp;quot):
        thread_local.session = requests.Session()
    return thread_local.session


def download_site(url):
    session = get_session()
    with session.get(url) as response:
        print(f&amp;quotRead {len(response.content)} from {url}&amp;quot)


def download_all_sites(sites):
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        executor.map(download_site, sites)


if __name__ == &amp;quot__main__&amp;quot:
    sites = [
        &amp;quothttps://www.jython.org&amp;quot,
        &amp;quothttp://olympus.realpython.org/dice&amp;quot,
    ] * 80
    start_time = time.time()
    download_all_sites(sites)
    duration = time.time() - start_time
    print(f&amp;quotDownloaded {len(sites)} in {duration} seconds&amp;quot)خروجی کد بالا در سیستم من. همانطور که مشاهده می کنید تفاوت چشمگیر است.Downloaded 160 in 6.9670493602752686 secondsنکات مربوط به مثال بالا:با استفاده از threading.local و قرار دادن thread_local.session = requests.Session یک session برای thread مورد نظر set کردیم.هدف استفاده از requests.Session به منظور افزایش سرعت در ریکوئست است که requests آن را هندل می کند.ماژول concurrent.futuresیک اینترفیس برای callable های در حال اجرای همزمان ایجاد می کند. این callable ها می توانند توسط ThreadPoolExecutor و یا ProcessPoolExecutor اجرا شوند که ما از ThreadPoolExecutor استفاده کرده ایم که در واقع یک abstract class است که متدهایی را برای اجرای همزمان فراهم می کند و مستقیماً استفاده نمی شود بلکه از طریق زیر کلاس ها از  آن استفاده می  شود (مانند map).در واقع این ماژول معادل  Thread + Pool + Executor است.قسمت Pool جایی است که  این object قصد دارد مجموعه ای از thread ها را ایجاد کند که هر یک از آنها می توانند همزمان اجرا شوند. سرانجام، executor بخشی است که می خواهد نحوه و زمان اجرای هر یک از thread های pool را کنترل کند. این درخواست را در pool اجرا خواهد کرد.تابع ()map تابع پاس داده شده را به همراه آرگومان ها به صورت همزمان در Pool اجرا خواهد کرد.در آخر اینکه با استفاده از ماژول فوق نیازی به ()thread.start و ()thread.join وجود ندارد و Executor وظیفه مدیریت Thread ها در Pool را بر عهده دارد.از آنجا که سیستم عامل تصمیم می گیرد که task ها کی اجرا شوند و کی بین task ها سويیچ اتفاق بیفتد، هر داده ای که بین thread ها به اشتراک گذاشته می شود باید محافظت شود و متاسفانه ()requests.Session، اینگونه نیست (thread-safe نیست). یکی از راه های thread-safe کردن استفاده از thread.local است. یک راه دیگر استفاده از threading.Lock است که در ThreadPoolExecutor پیاده سازی شده است.به دلیل مشکلاتی که ممکن است در برنامه نویسی multi threading اتفاق بیفتد، توصیه می شود هر جا نیاز به thread احساس شد نخست به asyncio فکر کنید.مشکلات احتمالی در برنامه نویسی multi threading:همگام سازی thread به عنوان مکانیزمی تعریف می شود که تضمین می کند دو یا چند  رشته همزمان به طور همزمان بخش خاصی از برنامه را که به عنوان Critical Section شناخته می شود اجرا نمی کنند. Critical Sectionرا نمی توان همزمان با بیش از یک فرآیند اجرا کرد بنابراین تمام پروسس ها باید منتظر بمانند تا در critical section خود اجرا شوند. سیستم عامل وظیفه مدیریت اجازه  دادن و ممانعت از ورود فرآیندها به بخش بحرانی را بر عهده دارد. مدیریت Critical Section مانع به وجود آمدن Race Condition می گردد. یک Race Condition زمانی رخ می دهد که دو یا چند رشته می توانند به داده های  مشترک دسترسی داشته باشند و همزمان سعی می کنند آن را تغییر دهند. از  آنجایی که الگوریتم زمان‌بندی رشته می‌تواند در هر زمانی بین رشته‌ها  جابه‌جا شود، ممکن است ترتیبی که thread تلاش می‌کند به داده‌های مشترک دسترسی پیدا کند، دچار مشکل شده و دو thread  همزمان به داده‌ها دسترسی پیدا کنند و آن را تغییر دهند.بن بست (Dead Lock):بن بست وضعیتی است که در آن دو یا چند thread برای همیشه منتظر در اختیار گرفتن lock برای دسترسی به داده های مورد نیاز می شوند. بن بست زمانی اتفاق می افتد که چندین thread به قفل های یکسانی نیاز دارند اما آنها را با ترتیب متفاوتی بدست می آورند. روش asyncioمفهوم کلی asyncio عبارت است از ایجاد یک شی، فراخوانی event loop و مشخص کردن اینکه کدام task در چه زمانی اجرا شود. event loop از وضعیت task های موجود آگاه است و می داند هر task در چه state ای قرار دارد. در asyncio دو کلمه کلیدی async و await مطرح است. await برای باز گرداندن کنترل به event loop استفاده می شود. async به عنوان یک flag در نظر گرفته می شود که مشخص می کند تابع تعریف شده شامل await خواهد بود.حال مثال بالا را این بار با asyncio پیاده سازی می کنیم:import asyncio
import time
import aiohttp


async def download_site(session, url):
    async with session.get(url) as response:
        print(&amp;quotRead {0} from {1}&amp;quot.format(response.content_length, url))


async def download_all_sites(sites):
    async with aiohttp.ClientSession() as session:
        tasks = []
        for url in sites:
            task = asyncio.ensure_future(download_site(session, url))
            tasks.append(task)
        await asyncio.gather(*tasks, return_exceptions=True)


if __name__ == &amp;quot__main__&amp;quot:
    sites = [
        &amp;quothttps://www.jython.org&amp;quot,
        &amp;quothttp://olympus.realpython.org/dice&amp;quot,
    ] * 80
    start_time = time.time()
    asyncio.get_event_loop().run_until_complete(download_all_sites(sites))
    duration = time.time() - start_time
    print(f&amp;quotDownloaded {len(sites)} sites in {duration} seconds&amp;quot)تابع asyncio.ensure_future()لیستی از task ها را در context manager ایجاد می کند و از آغاز کار آن ها اطمینان حاصل می کند. در زمانی که task ها ایجاد شدند متد asyncio.gather()سشن را تا زمان اتمام کار taskها باز نگه میدارد (alive).متدهای get_event_loop()و run_until_complete() در __main__ وظیفه در اختیار گرفتن event loop و اجرای تابع پاس داده شده به آن را بر عهده دارند.از مزایای asyncio نسبت به threading این است که مقیاس پذیری آن بهتر از thread است. همچنین ایجاد هر task در آن نسبت thread به منابع و زمان کمتری نیاز دارد.تفاوت asyncio و threadingمهمترین تفاوت asyncio و threading ها نحوه در اختیار قرار گرفتن نوبت انجام task هاست. در threadingسیستم عامل در هر لحظه می تواند اجرای یک thread را متوقف کرده و thread دیگر را اجرا کند (Pre-emptive multitasking) و به اصطلاح سیستم عامل تردها را Pre-emptive می کند تا بتواند بین آن ها سويیچ کند. Pre-emptive multitasking به معنای استفاده از مکانیزم وقفه است که فرآیند اجرای فعلی را به حالت تعلیق در می آورد و برای تعیین اینکه کدام فرآیند بعد از آن اجرا شود، بنابراین همه فرآیندها در هر لحظه مقداری از  زمان پردازنده را دراختیار می گیرند. فایده استفاده از Pre-emptive multitasking این است که نیازی نیست در کد برای سويیچ بین thread ها عملیات خاصی توسط برنامه نویس صورت بگیرد.در صورتی که asyncio از Cooperative multitasking استفاده می کند. به این معنی که در آن سیستم عامل سوئیچ را از یک process در حال اجرا به یک  process دیگر آغاز نمی کند. بلکه process ها بصورت داوطلبانه کنترل را به صورت دوره ای یا در حالت idle یا در اختیار می گیرند. به این نوع چند وظیفه ای مشارکتی گفته می شود.در asyncio به وضونح سرعت مناسبی را مشاهده کردیم ولی کد پیچیده تر از حالت های قبلی است. همچنین در این روش اگر یک task به هر دلیلی کنترل را به event loop ندهد راهی برای شکستن حلقه وجود نخواهد داشت و عملا برنامه را از کار خواهد انداخت.برنامه نویسی موازی (Parallelism):به معنی تقسیم یک مسئله به مسائل کوچکتر و سپردن آن ها به واحد های جداگانه برای پردازش است که این مسائل کوچک به صورت همزمان شروع به اجرا می کنند. مانند در اختیار داشتن دو thread است که روی دو هسته مختلف  یک CPU به صورت همزمان در حال اجرای تسک خود است. فرم های مختلفی از Parallel مانند bit-level instruction-level، data و task وجود دارد. ‌Multi tasking یکی از روش های پیاده سازی Parallelism است.روش Multitaskingبر خلاف رویکردهای قبلی، Multitasking از CPU های متعدد کامپیوتراستفاده می کند.از آنجا که ‌multi threading و asyncio روی یک هسته پردازنده اجرا می شوند، بنابراین می توان گفت در پایتون تنها multi processing امکان اجرای چندین task به صورت همزمان را در اختیار قرار می دهد. اما در سایر روش ها روند اجرای task ها را طوری نوبت دهی می کند که شبیه سازی صورت گرفته را می توان همزمانی نامید.در multiprocessing هر process را می توان به عنوان برنامه مجزا در نظر گرفت به صورتی که هر process منابع نرم افزاری و سخت افزاری مورد نیاز خود را اشغال می کند. در پایتون هر process حتی interpreter خود را دارد. multiprocessingروی core های مختلف یک CPU اجرا می شود و اجرا روی core های مختلف به این معنی ست که process ها به معنی واقعی همزمان اجرا می شوند.import requests
import multiprocessing
import time

session = None


def set_global_session():
    global session
    if not session:
        session = requests.Session()


def download_site(url):
    with session.get(url) as response:
        name = multiprocessing.current_process().name
        print(f&amp;quot{name}:Read {len(response.content)} from {url}&amp;quot)


def download_all_sites(sites):
    with multiprocessing.Pool(initializer=set_global_session) as pool:
        pool.map(download_site, sites)


if __name__ == &amp;quot__main__&amp;quot:
    sites = [
        &amp;quothttps://www.jython.org&amp;quot,
        &amp;quothttp://olympus.realpython.org/dice&amp;quot,
    ] * 80
    start_time = time.time()
    download_all_sites(sites)
    duration = time.time() - start_time
    print(f&amp;quotDownloaded {len(sites)} in {duration} seconds&amp;quot)این روش بسیار کوتاه تر از مثال asyncio است و در واقع کاملاً شبیه به مثال thread است. با multiprocessing همزمانی واقعی را تجربه خواهیم کرد ولی نسبت به روش های دیگر کند تر است.تمام نمونه های همزمانی در این مقاله فقط در یک پردازنده یا  core اجرا می شوند. دلایل این امر مربوط به طراحی  Python و چیزی به نام Global Interpreter Lock یا GIL است. GIL به عبارت ساده، یک mutex یا قفل است که فقط به یک thread اجازه می دهد تا کنترل interpreter پایتون را کنترل کند یعنی در هر لحظه از زمان تنها یک thread می تواند در حالت اجرا باشد. تأثیر GIL برای توسعه دهندگانی که برنامه هایsingle thread را  اجرا می کنند قابل مشاهده نیست، اما در برنامه های multi threading محسوس است. دلیل استفاده از GIL این است که پایتون برای مدیریت حافظه از memory management استفاده می کند. این بدان معناست  که اشیا ایجاد شده در پایتون دارای یک متغیر شمارنده reference هستند که تعداد reference هایی را که به آن شی اشاره می کنند نگه می داررد. وقتی این  تعداد به صفر می رسد، حافظه اشغال شده توسط شی آزاد می شود. مشکلی که GIL در صدد رفع آن بر آمده است این است که متغیر شمارش reference نیاز به محافظت در برابر شرایط race دارد (در آن دو thread به طور همزمان مقدار آن را افزایش یا کاهش می دهند). در این صورت احتمال این که حافظه هرگز آزاد نشود (leaked memory) یا حتی بدتر، حافظه به اشتباه آزاد شود وجود دارد.  راه حل پایتون برای رفع این مشکل قراردادن یک قفل واحد بر روی مفسر است که یک rule اضافه می کند که اجرای هر کد بایت پایتون مستلزم دستیابی به GIL است که این امر برنامه Python را single thread می کند.مثال زیر را در نظر بگیرید:import sys

a = []
b = a
sys.getrefcount(a)

3 #Outputنکات پایانی:در زمان تصمیم گیری برای استفاده از Concurrency گام اول این است که بفهمیم بار برنامه بر روی CPU است یا I/O. برنامه های I/O-bound به برنامه هایی گفته می شود که بیشتر وقت خود را در انتظار اتفاقات I/O می گذرانند در حالی که برنامه های CPU-bound وقت خود را صرف پردازش داده ها می کنند. مشکلات مربوط به CPU-bound تنها با استفاده از Multi processing به دست می  آیند. threading و asyncio به هیچ وجه به این نوع مشکلات کمک نمی کند.برای مشکلات I/O-bound، یک قانون کلی در انجمن پایتون وجود دارد: &quot;هر  زمان که می توانید از asyncio استفاده کنید، در صورت لزوم از thread استفاده کنید.منبع:با تشکر از Jim Anderson، منبع اصلی این مقاله:https://realpython.com/python-concurrency</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Fri, 09 Jul 2021 17:39:34 +0430</pubDate>
            </item>
                    <item>
                <title>حافظه heap و stack</title>
                <link>https://virgool.io/@mehdinazari/%D8%AD%D8%A7%D9%81%D8%B8%D9%87-heap-%D9%88-stack-kg9fzklzrhwb</link>
                <description>تعریف یک متغیر، ساخت instance، توابع، ایجاد یک thread و ... در برنامه نیاز به ذخیره سازی در حافظه دارند و همه آن ها فضایی از حافظه را اشغال می کنند. بنابراین لازم است تا یک برنامه نویس درک درستی از حافظه ای که در اختیار می گیرد داشته باشد. در این مقاله دو نوع از حافظه هایی که در زمان توسعه در اختیار برنامه نویس قرار می گیرد را بررسی می کنیم.حافظه stackدر بخش user-space حافظه قرار دارد و به صورت خودکار توسط CPU مدیریت می شود. متغیرهای غیر استاتیک، پارامتر های ارسالی به توابع و آدرس های مربوط به return توابع در این حافظه ذخیره می شوند. اندازه حافظه stack ثابت است به همین دلیل به آن static memory گفته می شود.در این حافظه اطلاعات پشت سر هم و به ترتیب قرار می گیرند به این صورت که آخرین داده ذخیره شده در بالای stack قرار می گیرد و به اصطلاح push می شود، حال اگر قصد برداشتن اطلاعات یا به اصطلاح pop کردن اطلاعات را داشته باشیم آخرین اطلاعات وارد شده در stack را در اختیار داریم. به این الگوریتم LIFO(Last In First Out) می گویند. مثال پر کاربرد در توضیح stack خشاب اسلحه (آخرین گلوله ای که در خشاب قرار داده می شود اولین گلوله ای است که شلیک می شود) و یا بشقاب های روی هم چیده شده (آخرین بشقابی که روی سایر بشقاب ها قرار داده می شود اولین بشقابی است که برداشته می شود) است.از آنجا که در حافظه stack نیازی به پیدا کردن فضای خالی در حافظه نیست و محل قرارگیری اطلاعات مشخص است (بالای حافظه) بنابراین این حافظه سریع تر از حافظه heap است. پارامتر ها و اطلاعات مربوط به توابع برای اجرا و کنترل آن ها در این حافظه ذخیره می شوند. تابعی که در بالای stack قرار  دارد تابعی است که در حال اجراست و بعد از اتمام کار تابع یا بروز خطا در اجرای تابع، حافظه اختصاص داده شده به تابع از stack حذف می شود و حافظه اشغال شده آزاد می شود. زمانی که یک thread تعریف می شود در stack قرار می گیرد.خطایی که ممکن است در اثر استفاده نادرست از حافظه stack رخ دهد stack overflow است. از جمله دلایل stack overflow یا سر ریز می توان به استفاده از متغیرهای محلی حجیم که منجر به کاهش فضای آزاد در stack و تخریب یا corrupt شدن بخشی از  memory اشاره کرد.حافظه Heapحافظه Heap در قست user-space حافظه مجازی قرار دارد و به صورت دستی توسط برنامه نویس مدیریت می شود. Heap مربوط به زمان اجرا (runtime) است و فضای اشغال شده در heap با اتمام کار تابع آزاد نمی شوند و تا زمانی که Garbage Collector این فضا را آزاد کند یا توسط برنامه نویس داده ها از حافظه heap پاک نشوند در این فضا باقی می ماند. اندازه حافظه heap متغیر است به همین دلیل به آن dynamic memory گفته می شود.در این نوع از حافظه برای ذخیره مقادیر ابتدا محاسبه ای توسط سیستم عامل صورت می گیرد تا اولین فضای حافظه ای که اندازه آن متناسب با اندازه ای که مورد نیاز ماست را پیدا کند، در صورت وجود این میزان از حافظه درخواستی آن را به صورت رزرو شده درمی آورد تا بقیه برنامه ها به این فضا دسترسی نداشته باشند، سپس آدرس ابتدای این فضای محاسبه شده به صورت یک اشاره گر (pointer) در اختیارمان قرار می دهد (یا به اصلاح allocating).متغیر ها به صورت پیش فرض در این حافظه قرار نمی گیرند و اگر قصد ذخیره متغیر ها در این حافظه را داشته باشیم باید به صورت دستی این اقدام انجام شود. متغیر هایی که در heap ذخیره می شوند به طور خودکار حذف نمی شوند و باید توسط برنامه نویس  و به صورت دستی حذف شوند. به طور کلی مدیریت حافظه heap به صورت دستی توسط برنامه نویس انجام می شود. آرایه های داینامیک در heap ذخیره می شوند.در صورتی که داده های ما از تعدا block های پشت سر هم در حافظه بیشتر باشد یا در صورت تغییر حجم داده ها در زمان های مختلف (تغییر سایز داده ها امکان پذیر است)، سیستم عامل داده ها را به صورت تکه تکه در block های حافظه ذخیره خواهد کرد.به دلیل محاسبات برای یافتن آدرس شروع حافظه و در اختیار گرفتن pointer حافظه heap نسبت به stack کندتر است. همچنین اگر داده ها به صورت پشت سر هم در block های حافظه قرار نگرفته باشند (این احتمال بسیار زیاد است) موجب کندی در بازیابی اصلاعات خواهد شد.وقتی که نمونه‌ای از یک کلاس ایجاد می‌کنیم این مقدار در Heap ذخیره می‌شود و وقتی که کار آن به پایان می رسد garbage collector حافظه را آزاد می کند و اگر موفق به این کار نشود، برنامه نویس باید به صورت دستی حافظه heap را آزاد کند، در غیر این صورت Memory leak اتفاق می افتد که به معنی in use نگه داشتن فضای حافظه برای اشیایی است که دیگر از آن ها در برنامه استفاده نمی شود و garbage collector قادر به آزاد سازی فضایی که آن ها اشغال کرده اند نیست.به طور کلی Value Type ها (primitive type) فضای زیادی اشغال نمی کنند و در stack ذخیره می شوند. برای دسترسی به متغیر های Value Type، مقدار آن به صورت مستقیم از حافظه stack خوانده می شود، مثلا زمانی که متغیری تعریف می کنیم آن متغیر به همراه مقدار آن در stack قرار می گیرد.برای دسترسی به متغیرهای Reference Type، ابتدا با مراجعه Stack و دریافت آدرس متغیر در Heap به شئ مربوط به متغیر دسترسی خواهیم داشت. Reference Type ها در حافظه heap نگهداری می شوند. زمانی که یک شی از کلاس ایجاد می کنیم ابتدا متغیری که شی به آن assign شده است با مقدار null در حافظه stack قرار می گیرد، سپس شی در heap ذخیره شده و پس از ذخیره سازی در heap آدرس شی در stack جایگزین null می شود.همچنین reference type ها به dynamic memory و value type ها به static memory نیاز دارند. در صورت نیاز به dynamic memory، باید امکان دسترسی به heap فراهم باشد و اگر نیازمند static memory باشیم، stack محل ذخیره سازی خواهد بود.</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Sun, 30 May 2021 15:19:09 +0430</pubDate>
            </item>
                    <item>
                <title>شی گرایی در پایتون</title>
                <link>https://virgool.io/coderlife/%D8%B4%DB%8C-%DA%AF%D8%B1%D8%A7%DB%8C%DB%8C-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-tiavcigbcihc</link>
                <description>پایتون به طور کامل از object oriented پشتیبانی میکند. همه چیز در پایتون کلاس و یا شی ای از یک کلاس است. string, list, dictionary, tuple و .. همه و همه از جمله object هایی هستند که از کلاس های built-in پایتون نمونه سازی شده اند.کلاسکلاس در زبان های برنامه نویسی به منزله الگو یا pattern برای شی است. در حقیقت ساختار شی را چگونگی تعریف کلاس مشخص می کند. هر کلاس شامل مجموعه ای از رفتار ها ست که متد ها آن ها را پیاده سازی می کنند و مجموعه ای از خصوصیات.کلاس با استفاده از کلمه کلیدی class، نام کلاس و علامت : و سپس با indent در ادامه اعضای کلاس تعریف می شود:class &lt;ClassName&gt;:
    &lt;statement1&gt;
    &lt;statement2&gt;
    .
    .
    &lt;statementN&gt;اعضای تشکیل دهنده کلاس:ویژگی های کلاس (Class Attributes) متغیر هایی هستند که به طور مستقیم در کلاس تعریف می شوند و با اعضای کلاس به اشتراک گذاشته می شوند. به صورت instance_ name.variable_name یا class_name.variable_name می توان به آن ها دسترسی پیدا کرد.class Student:
    school_name = &#039;XYZ School&#039;مقدار school_name برای همه نمونه ها یکسان خواهد ماند مگر اینکه صریحاً مقدار آن را در خود کلاس تغییر دهیم.&gt;&gt;&gt; Student.school_name 
&#039;XYZ School&#039; 
&gt;&gt;&gt; std = Student()
&gt;&gt;&gt; std.school_name 
&#039;XYZ School&#039;همانطور که مشخص است متغیر کلاس و متغیر های نمونه های ساخته شده از کلاس دقیقا یکی هستند.student1 = Student()
student2 = Student()
id(student1.school_name) == id(Student.school_name) == id (student2.school_name)برای تغییر مقدار متغیر های کلاس به صورت زیر عمل می کنیم (تغییر در نمونه تاثیری در مقدار متغیر کلاس ندارد).&gt;&gt;&gt; Student.school_name = &#039;ABC School&#039;
&gt;&gt;&gt; student1 = Student()
&gt;&gt;&gt; student1.school_name
&#039;ABC School&#039;
&gt;&gt;&gt; student1.school_name = &#039;My School&#039;
&gt;&gt;&gt; student1.school_name
&#039;My School&#039; 
&gt;&gt;&gt; Student.school_name
&#039;ABC School&#039; 
&gt;&gt;&gt; student2 = Student()
&gt;&gt;&gt; student2.school_name
&#039;ABC School&#039;سازنده (Constructor)هرگاه یک شی از کلاس ساخته می شود، متد سازنده به طور خودکار صدا زده می شود(پرانتز جلوی نام کلاس constructor را فراخوانی می کند). در پایتون متدهای ()__init__  و  ()__new__  به عنوان constructor شناخته می شود. ()__new__ هنگام ایجاد یک شی فراخوانی می شود و ()__init__ برای مقداردهی اولیه شی فراخوانی می شود، این متد با یک ورودی خاص به نام self است (self یک نام متعارف است ولی نامگذاری اولین پارامتر دلخواه است). متد سازنده برای تعریف attribute های یک نمونه و مقداردهی اولیه آنها استفاده می شود.class Student:
    def __init__(self): # constructor method
        print(&#039;Constructor invoked&#039;)با هر بار نمونه سازی از کلاس فوق تابع سازنده صدا زده می شود:&gt;&gt;&gt;s1 = Student()
Constructor invoked
&gt;&gt;&gt;s2 = Student()
Constructor invokedویژگی های وهله ای (Instance Attributes)شامل attribute ها و property هایی هستند که به یک instance اضافه می شوند. این اعضا در متد سازنده کلاس اضافه می شوند. در مثال زیر name و age ویژگی هایی هستند که به کلاس اضافه شده اند.class Student:

    def __init__(self): # constructor
        self.name = &amp;quot &amp;quot # instance attribute
        self.age = 0 # instance attributeبرای دسترسی به instance attribute ها به صورت زیر عمل میکنیم:&gt;&gt;&gt; std = Student()
&gt;&gt;&gt; std.name
&amp;quot&amp;quot
&gt;&gt;&gt; std.age
0و برای مقدار دهی به آنها به صورت زیر عمل میکنیم:&gt;&gt;&gt; std = Student()
&gt;&gt;&gt; std.name = &amp;quotBill&amp;quot  # assign value to instance attribute
&gt;&gt;&gt; std.age=25          # assign value to instance attribute
&gt;&gt;&gt; std.name             # access instance attribute value
Bill
&gt;&gt;&gt; std.age                # access value to instance attribute
25در صورتی که instance attribute ها را در متد سازنده مقدار دهی کنیم می توان نمونه سازی را به صورت زیر انجام داد:class Student:
    def __init__(self, name, age): 
        self.name = name
        self.age = age&gt;&gt;&gt; std = Student(&#039;Bill&#039;,25)
&gt;&gt;&gt; std.name
&#039;Bill&#039;
&gt;&gt;&gt; std.age
25پراپرتی ها (Properties)در پایتون property رابطی برای instance attribute ها فراهم می کند و آن ها را کپسوله می کند. property ها به دو صورت پیاده سازی می شوند: با استفاده از متد ()property و با استفاده از دکوراتور property@. هدف از تعریف یک property تغییر رفتار یک متد است، به نحوی  که بتوان از آن مانند یک attribute استفاده کرد. encapsulate و اعتبار سنجی روی attribute ها از مهمترین دلایل تعریف یک property است.تعریف property با استفاده از متد ()proprty:class Student:
    def __init__(self):
        self.__name=&#039;&#039;
    def setname(self, name):
        print(&#039;setname() called&#039;)
        self.__name=name
    def getname(self):
        print(&#039;getname() called&#039;)
        return self.__name
    name = property(getname, setname)در مثال بالا با استفاده از دو متد setname و getname یک property ایجاد کرده و آن را در متغیر name قرار دادیم. متد ()property متغیر name__ را به صورت private در آورده و برای دسترسی به آن باید از nameاستفاده کنیم که در واقع متد های getnam و setname را فراخوانی می کند.&gt;&gt;&gt; std = Student()
&gt;&gt;&gt; std.name=&amp;quotSteve&amp;quot
setname() called
&gt;&gt;&gt; std.name
getname() called
&#039;Steve&#039;برای تعریف یک property بهتر است از دکوراتور property@ استفاده کنیم که یک دکوراتور برای متد ()property است و یک property را تعریف می کند. مثال زیر را در نظر بگیرید:class User:
    def __init__(self, age):
        self.age = age
 
    @property
    def age(self):
        return self._ageدر مثال بالا property@ تابع ()age را تعریف می کند که متغیر private به نام age__ را برمی گرداند. در این مرحله می توان از ()age به عنوان یک property استفاده کرد.class User:
    def __init__(self, age):
        self.__age = None
        self.age = age
 
    @property
    def age(self):
        return self.__age
    
    @age.setter
    def age(self, value):
        if value &lt;= 0 or value &gt; 99:
            self.__age = 0
            print(&#039;Wrong age in input&#039;)
            return
        self.__age = value
        print(f&#039;Age days is {self.__age * 365}&#039;)در این مرحله متد ()age را به گونه ای overload کردیم که یکی از آنها عملیات set کردن و دیگری عملیات get را انجام می دهد. این property سن کاربر را دریافت کرده و در صورتی که بین ۰ و ۹۹ سال باشد تعداد روزهای آن را باز می گرداند.متد ها (Methods)در هر کلاس می توان با استفاده از کلمه کلیدی def یک تابع ایجاد کرد. معمولا (به جز classmethod ها) متدها self را به عنوان اولین پارامتر در ورودی می پذیرند که این نام قراردادی است و استفاده از نام دلخواه نیز مجاز است، هرچند استاندارد نیست. self به نمونه ساخته شده از کلاس اشاره می کند. class Student:
    def __init__(self, name, age): 
        self.name = name 
        self.age = age 
    def displayInfo(self): # class method
        print(&#039;Student Name: &#039;, self.name,&#039;, Age: &#039;, self.age)برای دسترسی به متد ها (instance method) ابتدا از کلاس instance گرفته و سپس به صورت instance_name.method_name به آن دسترسی خواهیم داشت.&gt;&gt;&gt; std = Student(&#039;Steve&#039;, 25)
&gt;&gt;&gt; std.displayInfo()
Student Name: Steve , Age: 25با استفاده از ()type می توان به نام کلاس از instance یک دسترسی پیدا کرد:&gt;&gt;&gt; title = &#039;python&#039;
&gt;&gt;&gt; print(type(title))
&lt;class &#039;str&#039;&gt;کلاس ها با استفاده از pass می توانند هیچ عضوی نداشته باشد، مانند کلاس زیر:class Student:
    passکلمه کلیدی pass یک null operation است که وقتی که اجرا شود هیچ اتفاقی نمی افتد. در مواقعی کاربرد دارد که برای پرهیز از دریافت خطا نیاز باشد یک بلاک هیچ کاری نکند، مثلا هنوز پیاده سازی تکمیل نشده است . نمونه سازی (instantiation)برای نمونه سازی از کلاس تنها کافی است نام کلاس را شبیه به اجرای یک کلاس بنویسیم:student = Student()اگر در متد سازنده instance variable ست شده باشد آنگاه بایددر زمان نمونه سازی مقادیر مربوط به آن ها را در instance  قرار داد:student = Student(instancevariable1, ... instance_variablen)برنامه نویسی شی گرا (Object Oriented Programming)شی گرایی یکی از روش های برنامه نویسی است که امکان استفاده مجدد (Code reusability) از کد ها را فراهم می کند و ساختار منسجم برنامه های ایجاد شده با این روش باعث محبوبیت در بین برنامه نویسان است.تکنیک های شی گرایی عبارت است از: inheritance, polymorphism, abstraction, ... .ارث بریبا فرض اطلاع از مفهوم ارث بری به سراغ پیاده سازی inheritance در پایتون می رویم:کلاس child از کلاس parent ارث بری می کند (inherit می شود) اگر داخل پرانتز بعد از نام کلاس child نام کلاس parent نوشته شود. به کلاس parent کلاس base یا پدر می گویند و به کلاسی را که ارث بری می کند کلاس فرزند گفته می شود.class Parent:
    statements
                    
class Child(Parent):
    statementsتمام مقادیر و متد های کلاس parent در کلاس child نیز در دسترس است و ارث بری این گونه موجب استفاده مجدد از کد ها می شود. class QuadriLateral:
    def __init__(self, a, b, c, d):
        self.side1=a
        self.side2=b
        self.side3=c
        self.side4=d

    def perimeter(self):
        p=self.side1 + self.side2 + self.side3 + self.side4
        print(&amp;quotperimeter=&amp;quot,p)در کلاس QuadriLatral (چهار ضلعی) چهار ضلع را به عنوان instance variable تعریف کرده ایم و تابع perimeter مجموع ضلع های نمونه ساخته شده را برمی گرداند.&gt;&gt;&gt; q1 = QuadriLateral(7, 5, 6, 4)
&gt;&gt;&gt; q1.perimeter()
perimeter=22حال ارث بری را در کلاس جدید اعمال می کنیم:class Rectangle(QuadriLateral):
    def __init__(self, a, b):
        super().__init__(a, b, a, b)از آنجا که کلاس  QuadriLateral در سازنده خود instance variable هایی را دریافت می کند، کلاس فرزند هم باید آن ها را به کلاس پدر ارسال کند، کلمه کلیدی super به کلاس پدر اشاره می کند. در مثال بالا کلاس فرزند instance variable ها را به سازنده کلاس پدر ارسال کرده است.&gt;&gt;&gt; r1 = Rectangle(10, 20)
&gt;&gt;&gt; r1.perimeter()
perimeter = 60همانطور که مشاهده می کنید کلاس فرزند متد perimeter را از کلاس پدر به ارث برده است.ارث بری چندگانهپایتون مانند ++C و برخلاف java و #C از ارث بری چندگانه (Multi Inheritance) پشتیبانی می کند. class Base1(object): 
    def __init__(self):
        self.str1 = &amp;quotGeek1&amp;quot
        print(&amp;quotBase1&amp;quot) 

class Base2(object): 
    def __init__(self): 
        self.str2 = &amp;quotGeek2&amp;quot		
        print(&amp;quotBase2&amp;quot) 

class Derived(Base1, Base2): 
    def __init__(self): 
        Base1.__init__(self) 
        Base2.__init__(self) 
        print(&amp;quotDerived&amp;quot) 
    def printStrs(self): 
        print(self.str1, self.str2) 

ob = Derived() 
ob.printStrs() خروجی:Base1
Base2
Derived
Geek1 Geek2ارث بری چند سطحی (Multilevel inheritance)زمانی که ارث بری در چند مرحله و از کلاسی به کلاس دیگر انجام شود به آن Multilevel inheritance گفته می شود.class Base(object): 
    def __init__(self, name): 
        self.name = name
    def getName(self): 
        return self.name 

class Child(Base): 
    def __init__(self, name, age): 
        Base.__init__(self, name) 
        self.age = age 
    def getAge(self): 
        return self.age
 class GrandChild(Child):
    def __init__(self, name, age, address): 
        Child.__init__(self, name, age) 
        self.address = address 

    def getAddress(self): 
         return self.address	

g = GrandChild(&amp;quotGeek1&amp;quot, 23, &amp;quotNoida&amp;quot) 
print(g.getName(), g.getAge(), g.getAddress()) خروجی:Geek1 23 Noida()بازنویسی متد (Overriding in Python)در صورت لزوم می توان متد های کلاس پدر را در کلاس فرزند بازنویسی (override) کرد. instance به هر دو متد دسترسی خواهد داشت اما در زمان initialize متد override شده را فراخوانی می کند.class Rectangle(QuadriLateral):
    def __init__(self, a,b):
        super().__init__(a, b, a, b)

    def area(self):
        a = self.side1 * self.side2
        print(&amp;quotarea of rectangle=&amp;quot, a)
class Square(Rectangle):
    def __init__(self, a):
        super().__init__(a, a)
    def area(self):
        a = pow(self.side1, 2)
        print(&#039;Area of Square: &#039;, a)آنجا همانطور که مشاهده می کنید متد override شده در کلاس Square (کلاس فرزند) اجرا خواهد شد.&gt;&gt;&gt;s = Square(10)
&gt;&gt;&gt;s.area()
Area of Square: 100چند ریختی (Polymorphism)چند ریختی یا polymorphism امکان تعریف متدهای همنام کلاس پدر در کلاس فرزند است. در حقیقت چند ریختی به معنی استفاده از توابع با نام های یکسان و فرم های متفاوت است.چند ریختی با استفاده از تابعدر این روش با استفاده از تابعی که در ورودی object دریافت می کند و متد مربوط به آن object را فراخوانی می کند polymorphism را پیاده سازی می کنند.class Bear(object):
    def sound(self):
        print(&amp;quotGroarrr&amp;quot)
    
class Dog(object):
    def sound(self):
        print(&amp;quotWoof woof!&amp;quot)
    
def make_sound(animalType):
    animalType.sound()
    

bearObj = Bear()
dogObj = Dog()
    
make_sound(bearObj)
make_sound(dogObj)در این مثال تابع makeSound در ورودی object کلاس را دریافت کرده و متد مربوط به آن را اجرا می کند.چند ریختی با استفاده از متد های کلاسclass Bird:
    def intro(self):
        print(&amp;quotThere are different types of birds&amp;quot)
    def flight(self):
        print(&amp;quotMost of the birds can fly but some cannot&amp;quot)

class Parrot(Bird):
    def flight(self):
        print(&amp;quotParrots can fly&amp;quot)

class Penguin(Bird):
    def flight(self):
        print(&amp;quotPenguins do not fly&amp;quot)


obj_bird = Bird()
obj_parr = Parrot()
obj_peng = Penguin() 

obj_bird.intro()
obj_bird.flight() 

obj_parr.intro()
obj_parr.flight() 
obj_peng.intro()
obj_peng.flight()همانگونه که در خروجی مشاهده می کنیم کلاس های Penguin و parrot متد flight را override کرده اند.There are different types of birds
Most of the birds can fly but some cannot
There are different types of bird
Parrots can fly
There are many types of birds
Penguins do not flyچند ریختی با استفاده از abstract در این روش تمام متدهایی که کلاس فرزند باید پیاده سازی کند را در یک کلاس abstract قرار داده و بدنه متد ها در کلاس abstract شامل NotImplementedErro باشد. در این صورت کلاس فرزند موظف است متدهای کلاس پدر را پیاده سازی کند و هر کلاس آن گونه که لازم است پیاده سازی را انجام می دهد.class Document:
    def __init__(self, name):
        self.name = name
    
    def show(self):
        raise NotImplementedError(&amp;quotSubclass must implement abstract method&amp;quot)
    
class Pdf(Document):
    def show(self):
        return &#039;Show pdf contents!&#039;

class Word(Document):
    def show(self):
        return &#039;Show word contents!&#039;

documents = [Pdf(&#039;Document1&#039;),
Pdf(&#039;Document2&#039;),
Word(&#039;Document3&#039;)]

for document in documents:
    print(document.name + &#039;: &#039; + document.show())خروجیDocument1: Show pdf contents!
Document2: Show pdf contents!
Document3: Show word contents!رابط کاربری (Interface)استفاده مهم interface در زبان هایی که single inheritance هستند به این دلیل است که امکان ارث بری یک کلاس از چندین کلاس وجود ندارد ولی ارث بری از چند interface ممکن است. در پایتون به دلیل پشتیبانی از multi inheritance نیاز به interface ضروری به نظر نمی رسد. اانتزاعی (Abstraction)کلاسی که شامل یک یا چند متد abstract باشد را کلاس abstract می گویند. یک متد abstract متدی است که اعلان (declaration) می شود ولی شامل بدنه پیاده سازی شده نیست. کلاس abstract معمولا به عنوان base کلاس مورد استفاده قرار می گیرند. abstract ها زمانی استفاده می شوند که بخواهیم برای یک متد چندین پیاده سازی مختلف انجام دهیم یا کلاس هایی وجود دارند که متد خاصی را به شیوه های مختلف پیاده سازی می کنند.برای ایجاد کلاس abstract در پایتون از کتابخانه abc استفاده می کنیم:from abc import ABC, abstractmethod 

class Animal(ABC): 
    @abstractmethod
    def move(self): 
        pass

class Human(Animal): 
    def move(self): 
        print(&amp;quotI can walk and run&amp;quot) 

class Snake(Animal): 
    def move(self): 
        print(&amp;quotI can crawl&amp;quot) 

class Dog(Animal): 
    def move(self): 
        print(&amp;quotI can bark&amp;quot) 

class Lion(Animal): 
    def move(self): 
        print(&amp;quotI can roar&amp;quot) 

dog = Dog() 
dog.move()خروجیI can barkدر صورتی که از یک کلاس abstract نمونه سازی کنیم با خطای زیر مواجه می شویم:&gt;&gt;&gt; animal = Animal()
Traceback (most recent call last):
  File &amp;quot/home/ffe4267d930f204512b7f501bb1bc489.py&amp;quot, line 19, in 
    c=Animal()
TypeError: Can&#039;t instantiate abstract class Animal with abstract methods moveبا استفاده از دکوراتورabc.abstractproperty@می توان property های abstract تعریف کردimport abc 
from abc import ABC, abstractmethod 

class parent(ABC): 
    @abc.abstractproperty 
    def geeks(self): 
        return &amp;quotparent class&amp;quot

class child(parent): 
    @property
    def geeks(self): 
        return &amp;quotchild class&amp;quot

try: 
    r = parent() 
    print(r.geeks) 

except Exception as err: 
    print (err) 
    r = child() 
    print (r.geeks) کلاس abstract را با استفاده از NotImplemetError می توان به صورت ضمنی پیاده سازی کرد به این صورت که متدهایی که در باید کلاس فرزند پیاده سازی شوند را در کلاس پدر اعلان کرده و کلاس اکسپشن NotImplementedError را raise می کنیم. در این صورت کلاس هایی که از کلاس پدر ارث بری می کنند چنانچه متدها را پیاده سازی نکنن با خطا مواجه خواهند شد.class Document:
    def __init__(self, name):
        self.name = name
    def show(self):
        raise NotImplementedError(&amp;quotThis method is not impelemented&amp;quot)

class PDF(Document):
    def show(self):
        print(&amp;quotPDF Document has been shown&amp;quot)در صورت فراخوانی تابع show از کلاس Document با خطای زیر مواجه می شوویم:document = Document(&#039;name&#039;)
document.show()NotImplementedError: This method is not impelemented</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Thu, 08 Apr 2021 20:19:28 +0430</pubDate>
            </item>
                    <item>
                <title>دیتابیس MongoDB - دستورات پیشرفته</title>
                <link>https://virgool.io/@mehdinazari/%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-mongodb-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1%D8%A7%D8%AA-%D9%BE%DB%8C%D8%B4%D8%B1%D9%81%D8%AA%D9%87-dz8vcgh8z3oh</link>
                <description>در دو بخش قبلی مفاهیم و دستورات مقدماتی MongoDB را بررسی کردیم. در این بخش به دستورات کمی advanced تر در MongoDB می پردازیم.پروجکشن (projection)به معنای محدودیت فیلدها در document های حاصل از نتیجه select در خروجی است. متد find یک پارامتر اختیاری ورودی دیگر که لیستی از فیلد هایی است که باید در خروجی نمایش داده شوند یا نمایش داده نشوند را دریافت می کند. این پارمتر ها با key که نام فیلد مورد نظر و value صفر یا یک مشخص می شود. دستور زیر شکل کلی projection را در MongoDB نمایش می دهد:&gt;db.COLLECTION_NAME.find({},{KEY:1})مثال&gt;db.mycol.find({},{&amp;quottitle&amp;quot:1,_id:0})
{&amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}
{&amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{&amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}نکته: باید دقت داشت که id_ همواره در خروجی نمایش داده می شود. برای عدم نمایش id_ باید مقدار آن را در projection برابر صفر قرار داد.متد Limitبرای دریافت و نمایش تعداد خاصی از document های حاصل از select از این متد استفاده می شود.&gt;db.COLLECTION_NAME.find().limit(NUMBER)مثال&gt;db.mycol.find({},{&amp;quottitle&amp;quot:1,_id:0}).limit(2)
{&amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}
{&amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}متد Skipبرای اینکه از تعداد خاصی از document های حاصل از select چشم پوشی (پرش) کنیم از این متد استفاده می شود.&gt;db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)مثال&gt;db.mycol.find({},{&amp;quottitle&amp;quot:1,_id:0}).limit(1).skip(1)
{&amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}متد Sortبا استفاده از این متد مطابق دستور زیر می توان ترتیب قرارگیری document ها را براساس فیلد مورد نظر با مقادیر 1و 1- مشخص کرد. &gt;db.COLLECTION_NAME.find().sort({KEY:1})مثال&gt;db.mycol.find({},{&amp;quottitle&amp;quot:1,_id:0}).sort({&amp;quottitle&amp;quot:-1})
{&amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}
{&amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{&amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}شاخص گذاری (Indexing)شاخص ها یا Index ها به منظور ایجاد query های کارامد تر استفاده می شوند. با تعریف index روی یک فیلد یا فیلدها، داده های collection براساس فیلد یا فیلد های index شده مرتب شده و در زمان بازیابی با سرعت بیشتزی query اجرا شده و در اختیار قرار می گیرد.متد createIndexبرای ایجاد یک index روی فیلد از دستور زیر استفاده می کنیم:&gt;db.COLLECTION_NAME.createIndex({KEY:1})مثال&gt;db.mycol.createIndex({&amp;quottitle&amp;quot:1})
{
	&amp;quotcreatedCollectionAutomatically&amp;quot : false,
	&amp;quotnumIndexesBefore&amp;quot : 1,
	&amp;quotnumIndexesAfter&amp;quot : 2,
	&amp;quotok&amp;quot : 1
}نکته: برای تعریف همزمان چند فیلد به صورت index به صورت زیر عمل میکنیم:&gt;db.mycol.createIndex({&amp;quottitle&amp;quot:1,&amp;quotdescription&amp;quot:-1})متد dropIndexبرای حذف یک index از این متد استفاده می شود.&gt;db.COLLECTION_NAME.dropIndex({KEY:1})مثال&gt; db.mycol.dropIndex({&amp;quottitle&amp;quot:1})
{
	&amp;quotok&amp;quot : 0,
	&amp;quoterrmsg&amp;quot : &amp;quotcan&#039;t find index with key: { title: 1.0 }&amp;quot,
	&amp;quotcode&amp;quot : 27,
	&amp;quotcodeName&amp;quot : &amp;quotIndexNotFound&amp;quot
}متد dropIndexesاین متد چند index را به صورت همزمان حذف می کند.&gt;db.COLLECTION_NAME.dropIndexes()مثال&gt;db.mycol.dropIndexes({&amp;quottitle&amp;quot:1,&amp;quotdescription&amp;quot:-1})
{ &amp;quotnIndexesWas&amp;quot : 2, &amp;quotok&amp;quot : 1 }متد getIndexesبرای دریافت index های یک collection از این متد استفاده می شود.db.COLLECTION_NAME.getIndexes()مثال&gt; db.mycol.getIndexes()
[
	{
		&amp;quotv&amp;quot : 2,
		&amp;quotkey&amp;quot : {
			&amp;quot_id&amp;quot : 1
		},
		&amp;quotname&amp;quot : &amp;quot_id_&amp;quot,
		&amp;quotns&amp;quot : &amp;quottest.mycol&amp;quot
	},
	{
		&amp;quotv&amp;quot : 2,
		&amp;quotkey&amp;quot : {
			&amp;quottitle&amp;quot : 1,
			&amp;quotdescription&amp;quot : -1
		},
		&amp;quotname&amp;quot : &amp;quottitle_1_description_-1&amp;quot,
		&amp;quotns&amp;quot : &amp;quottest.mycol&amp;quot
	}
]این سه بخش مقدمه ای بود بر  MongoDB که امیدوارم مفید بوده باشه. با آرزوی موفقیت.</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Sat, 20 Feb 2021 17:52:15 +0330</pubDate>
            </item>
                    <item>
                <title>دیتابیس MongoDB - دستورات مقدماتی</title>
                <link>https://virgool.io/@mehdinazari/%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-mongodb-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1%D8%A7%D8%AA-%D9%85%D9%82%D8%AF%D9%85%D8%A7%D8%AA%DB%8C-zfvxzeikhlx8</link>
                <description> در قسمت قبلی مفاهیم MongoDB را به اختصار توضیح دادم. در این بخش به شرح دستورات ابتدایی در MongoDB می پردازم. ساخت دیتابیس (create database):در MongoDB برای ساخت دیتابیس از &lt;use &lt;DB_NAME  استفاده می شود.برای مثال تکه کد زیر دیتابیس mydb را ایجاد (رزرو) کرده و به آن connect می شود. در ادامه توضیح داده می شود که این دستور به منزله ساخت دیتابیس نیست.&gt; use mydb
switched to db mydbبرای مشاهده دیتابیس connect شده از دستور زیر استفاده می کنیم:&gt; db
mydbبرای مشاهده لیست دیتابیس ها از دستور زیر استفاده می کنیم:&gt; show dbs
admin   0.000GB
config  0.000GB
local   0.000GBنکته: برای نمایش دیتابیسی که به تازگی ساخته شده است باید حتما یک رکورد در آن insert کرد.حدف دیتابیس (drop database)برای حذف یک دیتابیس از دستور زیر استفاده می کنیم:db.dropDatabase()مثال&gt;show dbs
local      0.78125GB
mydb       0.23012GB
test       0.23012GB
mydb 0.840256B&gt;db.dropDatabase()
&gt;{ &amp;quotdropped&amp;quot : &amp;quotmydb&amp;quot, &amp;quotok&amp;quot : 1 }&gt;show dbs
local      0.78125GB
test       0.23012GBساخت یک collection:db.createCollection(name, options)در دستور بالا name نام collection و option که اختیاری است تنظیمات مربوط به size و indexing را مشخص می کند و از بین گزینه های (capped, autoIndexId, size, max) انتخاب می شود.مثال&gt;use test
switched to db test
&gt;db.createCollection(&amp;quotmycollection&amp;quot)
{ &amp;quotok&amp;quot : 1 }برای نمایش لیست collection های یک دیتابیس از دستور زیر استفاده می کنیم:&gt;use test
switched to db test
&gt;show collections
mycollectionنکته: در MongoDB نیازی به ساخت collection نیست، با insert اولین مقدار collection به صورت اتوماتیک ساخته می شود.حذف یک collection:از دستور زیر برای حذف یک collection استفاده می شود:db.COLLECTION_NAME.drop()انواع data type در MongoDB:در MongoDB هم مانند سایر پایگاه داده ها انواع مختلف data type را در اختیار داریم. از انواع دیتا تایپ های مورد استفاده می توان بهString, Boolean, Double, Arrays, Timestamp, Object, Null, Symbol, Date, Object ID, Binary data, Code و Regular expression اشاره کرد.ورود اطلاعات (Insert):ورود اطلاعات در MongoDB با استفاده از دستور db.COLLECTION_NAME.insert(document) صورت می گیرد.مثال&gt; db.users.insert({
... _id : ObjectId(&amp;quot507f191e810c19729de860ea&amp;quot),
... title: &amp;quotMongoDB Overview&amp;quot,
... description: &amp;quotMongoDB is no sql database&amp;quot,
... by: &amp;quottutorials point&amp;quot,
... url: &amp;quothttp://www.tutorialspoint.com&amp;quot,
... tags: [&#039;mongodb&#039;, &#039;database&#039;, &#039;NoSQL&#039;],
... likes: 100
... })
WriteResult({ &amp;quotnInserted&amp;quot : 1 })نکته: در صورتی که collection مورد نظر وجود نداشته باشد آنگاه MongoDB آن را ساخته و سپس insert را انجام می دهد.نکته: در صورتی که id_ را مشخص نکنیم آنگاه MongoDB به صورت اتوماتیک یک فیلد با مقدار منحصر به فرد از نوع unique ObjectId در collection ایجاد می کند.متد ()insertOne:&gt; db.empDetails.insertOne(
	{
		First_Name: &amp;quotRadhika&amp;quot,
		Last_Name: &amp;quotSharma&amp;quot,
		Date_Of_Birth: &amp;quot1995-09-26&amp;quot,
		e_mail: &amp;quotradhika_sharma.123@gmail.com&amp;quot,
		phone: &amp;quot9848022338&amp;quot
	})
{
	&amp;quotacknowledged&amp;quot : true,
	&amp;quotinsertedId&amp;quot : ObjectId(&amp;quot5dd62b4070fb13eec3963bea&amp;quot)
}متد ()insertMany:برای insert چند رکورد همزمان از این متد استفاده می شود.&gt; db.empDetails.insertMany(
	[
		{
			First_Name: &amp;quotRadhika&amp;quot,
			Last_Name: &amp;quotSharma&amp;quot,
			Date_Of_Birth: &amp;quot1995-09-26&amp;quot,
			e_mail: &amp;quotradhika_sharma.123@gmail.com&amp;quot,
			phone: &amp;quot9000012345&amp;quot
		},
		{
			First_Name: &amp;quotRachel&amp;quot,
			Last_Name: &amp;quotChristopher&amp;quot,
			Date_Of_Birth: &amp;quot1990-02-16&amp;quot,
			e_mail: &amp;quotRachel_Christopher.123@gmail.com&amp;quot,
			phone: &amp;quot9000054321&amp;quot
		},
		{
			First_Name: &amp;quotFathima&amp;quot,
			Last_Name: &amp;quotSheik&amp;quot,
			Date_Of_Birth: &amp;quot1990-02-16&amp;quot,
			e_mail: &amp;quotFathima_Sheik.123@gmail.com&amp;quot,
			phone: &amp;quot9000054321&amp;quot
		}
	]
)
{
	&amp;quotacknowledged&amp;quot : true,
	&amp;quotinsertedIds&amp;quot : [
		ObjectId(&amp;quot5dd631f270fb13eec3963bed&amp;quot),
		ObjectId(&amp;quot5dd631f270fb13eec3963bee&amp;quot),
		ObjectId(&amp;quot5dd631f270fb13eec3963bef&amp;quot)
	]
}متد ()find:برای استخراج داده ها از collection ها از این متد استفاده می کنیم.&gt;db.COLLECTION_NAME.find()متد ()prety:برای نمایش ساختاریافته داده های استخراج شده از متد find از ()prety استفاده می کنیم.&gt;db.COLLECTION_NAME.find().pretty()متد ()findOne:معادل ()first یا ()one در سایر پایگاه های داده است و یک رکورد را برمیگرداند.&gt;db.COLLECTIONNAME.findOne()مثال&gt; db.mycol.findOne({title: &amp;quotMongoDB Overview&amp;quot})
{
	&amp;quot_id&amp;quot : ObjectId(&amp;quot5dd6542170fb13eec3963bf0&amp;quot),
	&amp;quottitle&amp;quot : &amp;quotMongoDB Overview&amp;quot,
	&amp;quotdescription&amp;quot : &amp;quotMongoDB is no SQL database&amp;quot,
	&amp;quotby&amp;quot : &amp;quottutorials point&amp;quot,
	&amp;quoturl&amp;quot : &amp;quothttp://www.tutorialspoint.com&amp;quot,
	&amp;quottags&amp;quot : [
		&amp;quotmongodb&amp;quot,
		&amp;quotdatabase&amp;quot,
		&amp;quotNoSQL&amp;quot
	],
	&amp;quotlikes&amp;quot : 100
}متد find به همراه AND:&gt;db.mycol.find({ $and: [ {&lt;key1&gt;:&lt;value1&gt;}, { &lt;key2&gt;:&lt;value2&gt;} ] })مثال&gt; db.mycol.find({$and:[{&amp;quotby&amp;quot:&amp;quottutorials point&amp;quot},{&amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot}]}).pretty()
{
	&amp;quot_id&amp;quot : ObjectId(&amp;quot5dd4e2cc0821d3b44607534c&amp;quot),
	&amp;quottitle&amp;quot : &amp;quotMongoDB Overview&amp;quot,
	&amp;quotdescription&amp;quot : &amp;quotMongoDB is no SQL database&amp;quot,
	&amp;quotby&amp;quot : &amp;quottutorials point&amp;quot,
	&amp;quoturl&amp;quot : &amp;quothttp://www.tutorialspoint.com&amp;quot,
	&amp;quottags&amp;quot : [
		&amp;quotmongodb&amp;quot,
		&amp;quotdatabase&amp;quot,
		&amp;quotNoSQL&amp;quot
	],
	&amp;quotlikes&amp;quot : 100
}متد find به همراه OR:&gt;db.mycol.find(  { $or: [ {key1: value1}, {key2:value2} ] } ).pretty()مثال&gt;db.mycol.find({$or:[{&amp;quotby&amp;quot:&amp;quottutorials point&amp;quot},{&amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot}]}).pretty()
{
   &amp;quot_id&amp;quot: ObjectId(7df78ad8902c),
   &amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot, 
   &amp;quotdescription&amp;quot: &amp;quotMongoDB is no sql database&amp;quot,
   &amp;quotby&amp;quot: &amp;quottutorials point&amp;quot,
   &amp;quoturl&amp;quot: &amp;quothttp://www.tutorialspoint.com&amp;quot,
   &amp;quottags&amp;quot: [&amp;quotmongodb&amp;quot, &amp;quotdatabase&amp;quot, &amp;quotNoSQL&amp;quot],
   &amp;quotlikes&amp;quot: &amp;quot100&amp;quot
}متد find به همراه AND و OR:مثال&gt;db.mycol.find({&amp;quotlikes&amp;quot: {$gt:10}, $or: [{&amp;quotby&amp;quot: &amp;quottutorials point&amp;quot},
   {&amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot}]}).pretty()
{
   &amp;quot_id&amp;quot: ObjectId(7df78ad8902c),
   &amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot, 
   &amp;quotdescription&amp;quot: &amp;quotMongoDB is no sql database&amp;quot,
   &amp;quotby&amp;quot: &amp;quottutorials point&amp;quot,
   &amp;quoturl&amp;quot: &amp;quothttp://www.tutorialspoint.com&amp;quot,
   &amp;quottags&amp;quot: [&amp;quotmongodb&amp;quot, &amp;quotdatabase&amp;quot, &amp;quotNoSQL&amp;quot],
   &amp;quotlikes&amp;quot: &amp;quot100&amp;quot
}متد find  به همراه NOR:&gt;db.COLLECTION_NAME.find( { $not: [ {key1: value1}, {key2:value2} ] } )مثال&gt; db.empDetails.find( { $nor:[ 40 {&amp;quotFirst_Name&amp;quot: &amp;quotRadhika&amp;quot}, &amp;quotLast_Name&amp;quot: &amp;quotChristopher&amp;quot} ] } ).pretty()
{
	&amp;quot_id&amp;quot : ObjectId(&amp;quot5dd631f270fb13eec3963bef&amp;quot),
	&amp;quotFirst_Name&amp;quot : &amp;quotFathima&amp;quot,
	&amp;quotLast_Name&amp;quot : &amp;quotSheik&amp;quot,
	&amp;quotAge&amp;quot : &amp;quot24&amp;quot,
	&amp;quote_mail&amp;quot : &amp;quotFathima_Sheik.123@gmail.com&amp;quot,
	&amp;quotphone&amp;quot : &amp;quot9000054321&amp;quot
}متد find  به همراه NOT:&gt;db.COLLECTION_NAME.find( { $NOT: [ {key1: value1}, {key2:value2} ] } ).pretty()مثال&gt; db.empDetails.find( { &amp;quotAge&amp;quot: { $not: { $gt: &amp;quot25&amp;quot } } } )
{
	&amp;quot_id&amp;quot : ObjectId(&amp;quot5dd6636870fb13eec3963bf7&amp;quot),
	&amp;quotFirst_Name&amp;quot : &amp;quotFathima&amp;quot,
	&amp;quotLast_Name&amp;quot : &amp;quotSheik&amp;quot,
	&amp;quotAge&amp;quot : &amp;quot24&amp;quot,
	&amp;quote_mail&amp;quot : &amp;quotFathima_Sheik.123@gmail.com&amp;quot,
	&amp;quotphone&amp;quot : &amp;quot9000054321&amp;quot
}متد Update:در MongoDB دو متد update و save جهت به روزرسانی داده های collection ها استفاده می شود.&gt;db.COLLECTION_NAME.update(SELECTION_CRITERIA, UPDATED_DATA)مثال &gt;db.mycol.update({&#039;title&#039;:&#039;MongoDB Overview&#039;},{$set:{&#039;title&#039;:&#039;New MongoDB Tutorial&#039;}})
WriteResult({ &amp;quotnMatched&amp;quot : 1, &amp;quotnUpserted&amp;quot : 0, &amp;quotnModified&amp;quot : 1 })نکته: به طور پیشفرض MongoDB ویرایش اطلاعات را روی یک document انجام می دهد. در صورتی که بحواهیم چندین document را ویرایش کنیم باید پارامتر multi را true ست کنیم.&gt;db.mycol.update({&#039;title&#039;:&#039;MongoDB Overview&#039;},
   {$set:{&#039;title&#039;:&#039;New MongoDB Tutorial&#039;}},{multi:true})متد updateOneاین متد تنها یک document را update می کند.&gt;db.COLLECTION_NAME.updateOne(&lt;filter&gt;, &lt;update&gt;)متد updateManyاین متد همه document هایی که با شرط مطابق باشند را update می کند.&gt;db.COLLECTION_NAME.update(&lt;filter&gt;, &lt;update&gt;)متد Saveاین متد document فعلی را با document ارسال شده جایگزین می کند.&gt;db.COLLECTION_NAME.save({_id:ObjectId(),NEW_DATA})مثال&gt;db.mycol.save(
   {
      &amp;quot_id&amp;quot : ObjectId(&amp;quot507f191e810c19729de860ea&amp;quot), 
      &amp;quottitle&amp;quot:&amp;quotTutorials Point New Topic&amp;quot,
      &amp;quotby&amp;quot:&amp;quotTutorials Point&amp;quot
   }
)حذف یک documentمتد remove برای حذف یک document از collection در دسترس است.&gt;db.COLLECTION_NAME.remove(DELLETION_CRITTERIA)مثال&gt;db.mycol.remove({&#039;title&#039;:&#039;MongoDB Overview&#039;})نکته: برای حذف یک document مطابق با شرط از دستور زیر استفاده می شود:&gt;db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)نکته: برای حذف document های یک collection از دستور زیر استفاده می کنیم:&gt; db.mycol.remove({})</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Tue, 02 Feb 2021 13:09:41 +0330</pubDate>
            </item>
                    <item>
                <title>پایگاه داده MongoDB − مفاهیم</title>
                <link>https://virgool.io/@mehdinazari/%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87-%D8%AF%D8%A7%D8%AF%D9%87-mongodb-%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-lk7cebiykbmp</link>
                <description>پایگاه داده MongoDB یک پایگاه داده cross-platform است که به زبان ++c نوشته شده است و از جمله دیتابیس های NoSQL محسوب می شود (دیتابیس Document oriented نیز خوانده می شود). دیتابیس های NoSQL:نوعی از پایگاه داده هستند که اصطلاحا schema less خوانده می شوند و به دلیل عدم وجود schema از سرعت بسیار بالاتری نسبت به دیتابیس های SQL برخوردارند. همچنین به دلیل عدم وجود ساختار پیچیده در دیتابیس های SQL، حجم دیتابیس های NoSQL کمتر از نوع SQL می باشد.به طور کلی می توان گفت دیتابیس های NoSQL مناسب برای ذخیره سازی داده های بدون ساختار با حجم بسیار بالا هستند.دیتابیس (database)دیتابیس یک container فیزیکی برای collection هاست. هر دیتابیس شامل فایل های مربوط به خود است.مجموعه (collection)معادل table در دیتابیس های رابطه ای هستند. collection ها شامل مجموعه ای از document های mongoDB هستند و بدون schema . هر collection می تواند فیلد های متفاوتی داشته باشد.سند (document)سند مجموعه ای از جفت key-value ها هستند. document ها اسکیمای dynamic دارند، به این معنی که document ها در یک collection می توانند شامل فیلد های متفاوت باشند و یا data type های متفاوتی داشته باشند. معادل مفاهیم در MongoDB و RDBMSویژگی های MongoDBبدون اسکیما (Schema less)ساختار روشن object هابی نیاز از join های پیچیدهمقیاس پذیری  (scale) دیتا مدل MongoDBدیتا مدل Embedded: در این نوع داده می توان داده های مربوط به هم را به صورت یک document در نظر گرفت. {
	_id: ,
	Emp_ID: &amp;quot10025AE336&amp;quot
	Personal_details:{
		First_Name: &amp;quotRadhika&amp;quot,
		Last_Name: &amp;quotSharma&amp;quot,
		Date_Of_Birth: &amp;quot1995-09-26&amp;quot
	},
	Contact: {
		e-mail: &amp;quotradhika_sharma.123@gmail.com&amp;quot,
		phone: &amp;quot9848022338&amp;quot
	},
	Address: {
		city: &amp;quotHyderabad&amp;quot,
		Area: &amp;quotMadapur&amp;quot,
		State: &amp;quotTelangana&amp;quot
	}
}دیتا مدل :Normalized: در این نوع مدل دیتا تا حد امکان در document های جدا قرار داده می شود.Employee:{
	_id: &lt;ObjectId101&gt;,
	Emp_ID: &amp;quot10025AE336&amp;quot
}Personal_details:{
	_id: &lt;ObjectId102&gt;,
	empDocID: &amp;quot ObjectId101&amp;quot,
	First_Name: &amp;quotRadhika&amp;quot,
	Last_Name: &amp;quotSharma&amp;quot,
	Date_Of_Birth: &amp;quot1995-09-26&amp;quot
}Contact:{
	_id: &lt;ObjectId103&gt;,
	empDocID: &amp;quot ObjectId101&amp;quot,
	e-mail: &amp;quotradhika_sharma.123@gmail.com&amp;quot,
	phone: &amp;quot9848022338&amp;quot
}Address:{
	_id: &lt;ObjectId104&gt;,
	empDocID: &amp;quot ObjectId101&amp;quot,
	city: &amp;quotHyderabad&amp;quot,
	Area: &amp;quotMadapur&amp;quot,
	State: &amp;quotTelangana&amp;quot
}در قسمت بعدی به شرح دستورات ابتدایی MongoDB می پردازم.</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Tue, 26 Jan 2021 17:49:27 +0330</pubDate>
            </item>
                    <item>
                <title>از decorator ها بیشتر بدانیم</title>
                <link>https://virgool.io/@mehdinazari/%D8%A7%D8%B2-decorator-%D9%87%D8%A7-%D8%A8%DB%8C%D8%B4%D8%AA%D8%B1-%D8%A8%D8%AF%D8%A7%D9%86%DB%8C%D9%85-bp3kufmb9hzx</link>
                <description>در برنامه نویسی decorator یک دیزاین پترن است که امکانات اضافی به یک object اضافه می کند. در پایتون دکوراتورها ابزاری هستند که امکانات اضافی را بدون تغییر تابع به توابع اضافه می کنند.دکوراتورها یکی از ابزارهای قدرتمند در python هستند که یک تابع را به عنوان argument می پذیرند و به کمک آنها می توان رفتار تابع argument را تغییر داد بدون اینکه تابع اصلی تغییر کند. به عبارت دیگر دکوراتورها این امکان را به برنامه نویس می دهند که رفتار توابع را به طور موقتی تغییر دهند. دکوراتورها با استفاده از decorator@ روی توابع اعمال می شوند.به طور کلی دکوراتور ها به صورت زیر تعریف می شوند:def mydecoratorfunction(some_function): # decorator function
    def inner_function(): 
        # write code to extend the behavior of some_function()
        some_function() # call some_function
        # write code to extend the behavior of some_function()
    return inner_function # return a wrapper functionدکوراتورها روش ساده برای اجرای توابع  higher-order هستند. توابع  higher-order توابعی هستند که یک یا چند تابع را به عنوان آرگومان ورودی دریافت می کنند و یا یک تابع را return می کنند.در دکوراتور، function ها به عنوان ورودی به تابع دیگر پاس داده می شود و سپس داخل تابع wrapper صدا زده می شود. هدف اصلی از نوشتن دکوراتورها جلوگیری از نوشتن کدهای تکراری است به این صورت که توابعی را یکبار نوشته و از آنها برای متدهای مختلف استفاده می کنیم. مانند authorization که با استفاده از @ در بالای متد هایی که نیاز به اعتبار سنجی دارند قرار داده می شود.توابع در پایتون object هستند، بنابراین می توانند refrence داده شوند یا به عنوان متغیر به تابع دیگر ارسال شوند و یا توسط تابع دیگر return شوند. همچنین توابع می توانند درون یکدیگر اجرا شوند و متغیر های خود را به توابع درونی پاس دهند.مثال زیر را در نظر بگیرید که تابعی را در ورودی دریافت می کند و زمان اجرای آن را محاسبه می کند:import time
import math


def calculate_time(func):
    def inner(*args, **kwargs):
        begin = time.time()
        func(*args, **kwargs)
        end = time.time()
        print(&amp;quotTotal time taken in : &amp;quot, func.__name__, end - begin)
    return innerحال از تابع calculate_time با استفاده از @ می توان به صورت دکوراتور برای توابع دیگر استفاده کرد:@calculate_time
def factorial(num):
    time.sleep(2)
    print(math.factorial(num))خروجی کد بالا به صورت زیر خواهد بود:&gt;&gt;&gt;factorial(10)

3628800
Total time taken in :  factorial 2.0061802864074707تشریح: در کد بالا تابع factorial(num) به عنوان ورودی به دکوراتور calculate_time ارسال می شود و در این دکوراتور اجرا شده و تابع  inner(*args, **kwargs) زمان اجرای آن را محاسبه می کند.زنجیره دکوراتورها:می توان دکوراتورها را به صورت زنجیره ای از رکوراتورها به صورت زیر استفاده کرد:def decor1(func):
    def inner():
        x = func()
        return x * x
    return inner

def decor(func):
    def inner():
        x = func()
        return 2 * x
    return inner

@decor1
@decor
def num():
    return 10print(num())خروجی کد بالا عدد 400 خواهد بود.دکوراتور با functools:import functools

def decorator(func):
    @functools.wraps(func)
    def wrapper_decorator(*args, **kwargs):
        value = func(*args, **kwargs)
        return value
    return wrapper_decoratorدکوراتورها با ورودی:def decorator(*args, **kwargs):
    print(&amp;quotInside decorator&amp;quot)
    def inner(func):
        print(&amp;quotInside inner function&amp;quot)
        print(&amp;quotI like&amp;quot, kwargs[&#039;like&#039;])
        func()
    return inner@decorator(like = &amp;quotgeeksforgeeks&amp;quot)
def func():
    print(&amp;quotInside actual function&amp;quot)با اجرای کد بالا خروجی زیر را خواهیم داشت:Inside decorator
Inside inner function
I like geeksforgeeks
Inside actual function</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Fri, 06 Nov 2020 16:03:53 +0330</pubDate>
            </item>
                    <item>
                <title>انواع متدهای زبان python</title>
                <link>https://virgool.io/@mehdinazari/%D8%A7%D9%86%D9%88%D8%A7%D8%B9-%D9%85%D8%AA%D8%AF%D9%87%D8%A7%DB%8C-%D8%B2%D8%A8%D8%A7%D9%86-python-pe4tvwhbnepf</link>
                <description>زبان python دارای سه نوع متد، شامل: Instance method, Class method و Static method است. متدهای یک کلاس به طور پیش فرض از نوع Instance method است و اگر بخواهیم تغییری در این روند ایجاد کنیم باید از decorator های مخصوص استفاده کنیم که در ادامه به شرح هرکدام می پردازیم (از decorator بیشتر بدانیم). متدهای نمونه (Instance method):رایج ترین و قدرتمندترین متدها در زبان پایتون هستند. این متدها از پارامتر self به عنوان اولین آرگومان در ورودی استفاده می کنند (بدیهی ست که استفاده از سایر ورودی ها امکان پذیر است). با استفاده از self که به Instance کلاس اشاره می کند، دسترسی به سایر متد ها و attributes های کلاس امکان پذیر است. Syntax:class C(object):
    def fun(self, arg1, arg2, ...):
       ....برای استفاده از instance method ها باید یک نمونه از آن ایجاد کرد و از اعضای آن ها استفاده کرد:c = C()
c.fun(&amp;quotarg1&amp;quot, &amp;quotarg2&amp;quot, ...)متدهایی که به این صورت تعریف شوند، با هر بار ایجاد نمونه از کلاس می توانند نتایج متفاوت داشته باشند. این متد ها با استفاده از self.__class__ به اعضای کلاس دسترسی دارند، بنابراین قادرند وضعیت class و وضعیت instance ساخته شده از کلاس را تغییر دهند.متدهای کلاس (Class method):این نوع از متد با استفاده از دکوراتور داخلی (builtin) classmethod@ ایجاد (و شناخته) می شوند. یک کلاس متد پارامتر cls را به عنوان اولین آرگومان در ورودی می پذیرند (مثل حالت قبل استفاده از سایر ورودی ها نیز امکان پذیر است). cls به اشیای درون کلاس اشاره می کند و نه نمونه ساخته شده از آن، بنابراین Class method ها می توانند وضعیت کلاس را تغییر دهند.Syntax:class C(object):
    @classmethod
    def fun(cls, arg1, arg2, ...):
       ....برای استفاده از کلاس متدها نیازی به ساخت نمونه از آن نیست و می توان از کلاس متدها به صورت زیر استفاده کرد:c = C.func(&amp;quotarg1&amp;quot, &amp;quotarg2&amp;quot)کلاس متدها محدود به کلاس هستند و نه نمونه ساخته شده (Instance) از کلاس و می توانند state کلاس را از طریق پارامتر cls تغییر دهند که تغییر در کلاس منجر به تغییر state نمونه های ساخته شده از کلاس نیز خواهد شد.عموما از کلاس متدها برای ایجاد factory method استفاده می شود. factory method همانند constructor ها یک نمونه از کلاس برای use case های مختلف برمی گردانند.متدهای استاتیک (Static method):این متد ها با استفاده از دکوراتور staticmethod@ ایجاد (و شناخته) می شوند. در ورودی این نوع متد ها پارامتر معناداری مانند cls یا self وجود ندارد اما مانند تمام متد ها امکان دریافت ورودی را دارند.این متدهای کاربرد زیادی در برنامه نویسی پایتون ندارند و به جای آن ها می توان از module functions (توابعی که در یک ماژول دیگر قرار دارد، مثلا ماژول utils) استفاده کرد. Syntax:class C(object):
    @staticmethod
    def fun(arg1, arg2, ...):
        ...استاتیک متدها نیز محدود به کلاس هستنداما قادر نیستند state کلاس یا نمونه ساخته شده از کلاس را تغییر دهند و تنها به داده هایی که به آنها دسترسی دارند محدود شده اند. به طور کلی استاتیک متدها اطلاعاتی از state کلاس یا نمونه ساخته شده از کلاس ندارند. استاتیک متدها در حقیقت چیزی جز یک callable در یک کلاس نیستند که برای دسترسی به آن ها نیازی به نمونه سازی از کلاس نیست.کاربرد استاتیک متدها در مواقعی است متد وظیفه پردازش مجزایی از سایر فعالیت اعضای کلاس را بر عهده دارد و نیاز به  بیشتر برای ایجاد متدهای کاربردی و یا محاسباتی است.مثال)from datetime import date


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def sayHello(self, name):
        return(f&amp;quotHello {name})

    @classmethod
    def fromBirthYear(cls, name, year):
        return cls(name, date.today().year - year)

    @staticmethod
    def isAdult(age):
        return age &gt; 18&gt;&gt;&gt; person1 = Person(&#039;mayank&#039;, 21)
&gt;&gt;&gt; person2 = Person.fromBirthYear(&#039;mayank&#039;, 1996)
&gt;&gt;&gt; print person1.age
&gt;&gt;&gt; print person2.age
&gt;&gt;&gt; print Person.isAdult(21)خروجی کد بالا به صورت زیر خواهد بود:21
21
True</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Fri, 06 Nov 2020 15:00:34 +0330</pubDate>
            </item>
                    <item>
                <title>زبان های برنامه نویسی static و dynamic</title>
                <link>https://virgool.io/coderlife/%D8%B2%D8%A8%D8%A7%D9%86-%D9%87%D8%A7%DB%8C-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-static-%D9%88-dynamic-fyifjbn0pnfg</link>
                <description>زبان های برنامه نویسی از لحاظ typing به دو دسته dynamic type و static type تقسیم می شوند. روند اجرای یک برنامه به این صورت است که کد نوشته شده توسط برنامه نویس به کدی که توسط ماشین قابل درک باشد تبدیل شده (کد compile یا interpret شده) و سپس این کد قابل درک توسط ماشیین اجرا می گردد. در زمان اجرای برنامه (run-time) یا در زمان compile برخی اعتبار سنجی ها روی برنامه صورت می گیرد که اساس تفاوت های زبان های static و dynamic را مشخص می کند.لازم به ذکر است که dynamic یا static بودن یک زبان نقطه قوت یا ضعف یک زبان محسوب نمی شود بلکه تنها در مواقع استفاده از زبان موجب راحتی استفاده از زبان می شود.زبان های dynamic به خاطر عدم نیاز به مشخص کردن نوع متغیر ها در زمان توسعه راحت تر هستند اما در زمان دیباگ ممکن است مشکلات خاص خود را داشته باشد، در صورتی که در زبان های static کامپایلر بخشی از خطاها را در زمان کامپایل مشخص می کند.زبان های برنامه نویسی dynamicبیشتر زبان های اسکریپتی در این دسته جای می گیرند. در زبان های dynamic نوع متغیر معمولا در زمان اجرا (run-time) و با توجه به مقدار متغیر مشخص می شود. بنابراین نیازی به مشخص کردن نوع متغیر در این گونه زبان ها نیست.در این نوع از زبان ها نیازی به اعلان (explicit declaration) متغیر قبل از استفاده نیست و می توان بلافاصله متغیر را مقدار دهی کرد و از آن استفاده نمود.name = &#039;mehdi&#039;
number = 10
average = 2.3
result = number * average /  2زبان های dynamic معمولا از نوع زبان های interpreter هستند. interpreter زبان در هنگام اجرا type checking را انجام می دهد، بنابراین این امکان وجود دارد که متغیر ها در طول اجرا، نوع متفاوتی داشته باشند.&gt;&gt;&gt; thing = &amp;quotHello&amp;quot
&gt;&gt;&gt; type(thing)
&lt;class &#039;str&#039;&gt;

&gt;&gt;&gt; thing = 28.1
&gt;&gt;&gt; type(thing)
&lt;class &#039;float&#039;&gt;برخی از زبان های dynamic شامل:‌ Perl, Ruby, Python, PHP, JavaScriptزبان های برنامه نویسی staticاین نوع از زبان ها معمولا از زبان های کامپایلری هستند. در اکثر زبان های استاتیک، type checking قبل از اجرای کد و در هنگام compile انجام می شود. بنابراین می توان گفت زبان هایی که در زمان compile باید نوع متغیرها مشخص باشند زبان های static نامیده می شوند.string name = &#039;mehdi&#039;;
int number = 10;
float average = 2.3مهمترین ویژگی استاتیک بودن یک زبان این است که بخش اعظم خطاها توسط کامپایلر برطرف شده و در هنگام اجرای کد احتمالا با خطای کمتری مواجه خواهیم بود.برخی از زبان های static شامل:‌ Go ،C، java، C#، C++، Haskell, Scala, Kotlin</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Sat, 22 Aug 2020 14:10:43 +0430</pubDate>
            </item>
                    <item>
                <title>ورژنینگ در تولید نرم افزار (Semantic Versioning)</title>
                <link>https://virgool.io/coderlife/%D9%88%D8%B1%DA%98%D9%86%DB%8C%D9%86%DA%AF-%D8%AF%D8%B1-%D8%AA%D9%88%D9%84%DB%8C%D8%AF-%D9%86%D8%B1%D9%85-%D8%A7%D9%81%D8%B2%D8%A7%D8%B1-semantic-versioning-cdy0krvuukny</link>
                <description>در این پست قصد دارم نحوه ورژنینگ رو در نرم افزار های در حال توسعه یا نرم افزار های ریلیز شده توضیح بدم. برای اینکه مشخص کنیم هر برنامه ریلیز شده یا در حال توسعه نسبت به نسخه قبلی چه تغییراتی داشته با استفاده از روشی که در آن هر نسخه را با اعدادی که با نقطه از هم جدا می شوند و هر عدد معنای خودشان را دارند مشخص می کنیم. یکی از روش های رایج ورژنینگ روش Semantic Versioning است که در ادامه به توضیح آن می پردازم.روش Semantic Versioningبرای مشخص کردن هر نسخه از برنامه نسبت به نسخه های دیگر از سه عدد استفاده می شود. به ترتیب از چپ به راست، عدد اول را major، عدد دوم را minor و عدد سوم را patch می نامند (major.minor.patch).میجر (Major): زمانی که تغییرات غیر قابل بازگشت به نسخه قبلی اعمال شده باشد این عدد اضافه می شود.ماینر (Minor):زمانی که یک فیچر به نرم افزار اضافه می شود این عدد را افزایش می دهیم.پچ (Patch): زمانی که باگ داخلی نرم افزار رفع می شود این عدد را افزایش می دهیم.شرایط Semantic Versioningاعداد مورد استفاده در major.minor.patch نباید منفی باشند.هر بار که یک نسخه ریلیز داده می شود، محتوای آن نباید دیگر تغییر داده شود. تغییرات بعدی مربوط به نسخه بعدی می شود.در زمان شروع توسعه برنامه major باید صفر در نظر گرفته شود.زمانی minor و patch اضافه می شود که تغییرات با نسخه قبلی سازگار باشد و منجر به ریلیز نسخه با major جدید نشود.زمانی که به minor یک عدد اضافه می شود patch باید 0 شود.زمانی که به major یک عدد اضافه می شود patch و minor باید 0 شود.می توان از اعداد و حروف و - نیز در قسمت patch استفاده کرد. این حروف شامل [9-a-zA-Z-0].      مانند: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.–.</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Thu, 20 Aug 2020 18:45:38 +0430</pubDate>
            </item>
                    <item>
                <title>همه چیز درباره سشن و کوکی</title>
                <link>https://virgool.io/@mehdinazari/%D9%87%D9%85%D9%87-%DA%86%DB%8C%D8%B2-%D8%AF%D8%B1%D8%A8%D8%A7%D8%B1%D9%87-%D8%B3%D8%B4%D9%86-%D9%88-%DA%A9%D9%88%DA%A9%DB%8C-q1ea8fnmf6pt</link>
                <description>در برنامه‌نویسی وب بسیار پیش می‌آید که نیاز به ذخیره اطلاعات در  متغیرهایی داشته باشیم که در سراسر پروژه در دسترس باشند. در این شرایط می‌توان از Session ها و Cookie ها استفاده کرد.کوکی (Cookie):پروتکل HTTP پروتکلی Stateless است به این معنی که اطلاعاتی از درخواست کننده را نزد سرور نگهداری نمی کند. بنابر این در درخواست های بعدی، امکان شناسایی طرفین درخواست وجود ندارد. با استفاده از cookie می توان برای شناسایی کاربران اطلاعات server را نزد client قرار داد.کوکی ها (Cookie) ها فایل های متنی هستند که توسط مرورگر Client در مرورگر وی و به صورت محلی (local) برای شناسایی کاربر ذخیره می شوند. کوکی ها طول عمر دارند و بنا به خواست توسعه دهنده تنظیم می شوند. کوکی های متعلق به یک دامنه، در اولین درخواست بین Client و Server رد  وبدل می شنود تا در درخواست های بعدی امکان شناسایی وجود داشته باشد. از آنجا که کوکی ها با جا به جا شدن از یک صفحه به صفحه دیگر و یا حتی بسته شدن  مرورگر از بین نمی روند، می توان از آنها برای ذخیره توکن کابر، ذخیره تنظیمات کاربر مانند اندازه فونت و رنگ اجزای صفحه، نام کاربری و … استفاده کرد. نکته مهم درباره  کوکی ها این است که کوکی ها در دسترس هستند و  دستکاری یا سرقت آن ها کاری دشوار نیست، بنا بر این نباید  قابل خواندن و حاوی اطلاعات مهم باشند.یک کوکی از بخش های زیر تشکیل شده است:تاریخ انقضا (Expire):تاریخ انقضا یا طول عمر کوکی.محتوا (Content):محتوای ذخیره شده در کوکی.دامنه (Domain):دامنه ای که کوکی در آن ایجاد می شود.مسیر (Path):مسیری که کوکی در آن ذخیره می شود.امنیت (Secure):اطلاعات امنیتی مربوط به سرویس دهنده های امن.انواع کوکی:کوکی های session:برای مواقعی که نیاز است یک کوکی به طور موقت استفاده شود از آنها استفاده میکنیم زیرا آنها در حافظه موقت ذخیره می شوند و تا زمانی که مرورگر کاربر بسته شود باقی می مانند.کوکی های امن یا secure:این کوکی ها رمزگذاری شده است و فقط در یک اتصال امن HTTPS کار می کند. برای نگهداری اطلاعات حساس از این نوع کوکی استفاده می شود. به دلیل اینکه این نوع کوکی رمزنگاری شده هستند از سایر انواع خود امن تر هستند.کوکی های پایدار یا Persistent:از آن ها برای ردیابی و  جمع آوری اطلاعات کاربر در طول یک بازه زمانی خاص استفاده می کنند.کوکی های HttpOnly :این کوکی ها فقط  توسط دامنه ای که آنها را ایجاد کرده اند می توانند مورد استفاده قرار بگیرند، همچنین نمی توانند توسط هیچ  پروتکلی غیر از HTTP استفاده شوند. فقط کوکی های session می توانند HttpOnly باشند.کوکی های شخص ثالث یا Third-Party:این کوکی ها متعلق به یک دامنه متفاوت، غیر از دامنه ای که آنها را ایجاد کرده است می باشند و می توانند تاریخچه مرور یک کاربر را در چندین وبسایت که از یک شبکه تبلیغاتی استفاده می کنند، ذخیره کنند. از آنجا که این کوکی ها در شبکه های تبلیغاتی برای تبلیغات هوشمند برای ردیابی اطلاعات استفاده می شود ممکن است به حریم خصوصی آسیب برساند. کوکی های زامبی:این نوع کوکی ها  در خارج از مرورگر ذخیره می شوند و پس از حذف شدن، خود را  بازیابی می کنند. آنها معمولا توسط سرویس های تجزیه و تحلیل و به این دلیل که اگر کاربر کوکی ها را حذف کرد، داده ها از بین نروند مورد استفاده قرار می گیرند. آنها همچنین می توانند برای اهداف مخرب مورد استفاده قرار  بگیرند، زیرا مرورگر نمی تواند وجود آن ها را کنترل کند. تنها محصولات امنیتی مثل آنتی ویروس ها هستند که می توانند کوکی های زامبی را شناسایی و  حذف کنند.سشن (Session):سشن (Session) برخلاف کوکی ها در سرویس دهنده (Server) ذخیره می شود. مکان ذخیره Session را میتوان تغییر داد ولی به صورت  پیشفرض در حافظه ذخیره می شود، به همین دلیل به سرعت قابل دسترسی هستند. به این دلیل که مقادیر Session عمومی نیست باید به ازای هر کاربر ایجاد گردد. بنابراین باید در هنگام ساخت یک Session، یک کوکی هم در سرویس گیرنده با مقدار آیدی Session ایجاد گردد.به طور پیش فرض، Session ها بعد از بسته شدن مرورگر، از بین خواخند رفت بنابر این در صورتی که اطلاعات حساس در آن ها قرار می گیرد باید مقدار آن ها در پایگاه داده ذخیره شوند.از sessionها باید فقط برای اطلاعات مهم استفاده کرد زیرا استفاده بیش از حد از آن ها می تواند موجب کاهش سرعت بارگذاری صفحات شود. مراحل ایجاد یک session: ایجاد یک session با Id منحصر به فرد.ایجاد یک cookie هم نام session در مرورگر کاربر.ایجاد یک فایل در دایرکتوری موقت مشخص شده بر روی سرور  با Id سشن.</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Sun, 03 May 2020 00:58:43 +0430</pubDate>
            </item>
                    <item>
                <title>3 دقیقه با Celery</title>
                <link>https://virgool.io/@mehdinazari/%D8%A8%D8%A7-celery-%D8%A8%DB%8C%D8%B4%D8%AA%D8%B1-%D8%A2%D8%B4%D9%86%D8%A7-%D8%B4%D9%88%DB%8C%D9%85-zdm1blggl0vr</link>
                <description>در مواقعی که ترافیک روی سرور زیاد باشد، برای کارهایی که نیاز به پاسخ­ دهی آنی ندارند، مانند پردازش تصویر یا خروجی پرس و جو­های پیچیده database، پاسخ دهی به کلاینت دچار وقفه خواهد شد. یکی از راه حل­ های این مشکل استفاده از task queue هایی مانند celery است. celery با استفاده از یک message broker نظیر redis یا RabbitMQ (از جمله message broker های شناخته شده برای صف بندی پیام یا message queueing)، task ها را در صف (ها) قرار می­ دهد (queueing) و به محض اینکه سرور قادر به پاسخگویی بود درخواست ها را به سمت سرور هدایت می­ کند.سلری (Celery) با زبان python و بصورت open source نوشته شده است و زبان های برنامه نویسی مانند php، Ruby و java نیز می­توانند از آن بهره­مند شوند.سلری یک task queue غیر همروند (asynchronous) است که بر اساس بهترین راه حل های مسائل سازمان ها ایجاد شده است و پروتکل AMQP را پیاده­ سازی می­کند. این پروتکل در مواقعی که سرعت تولید کننده (producer) و سرعت مصرف کننده (consumer) پیام یکسان نباشد، به منظور نگهداری پیام ها توسط یک یا چند صف (queue) کاربرد دارد. یکی از مهمترین مشکلات پروتکل AMQP پیچیدگی زیاد در پیکربندی و نگهداری آن در پروژ است. از آنجا که مراحل نصب celery، پیکربندی و استفاده از آن آسان است محبوبیت زیادی را در بین توسعه­ دهندگان کسب کرده است.در حقیقت می ­توان celery را به عنوان تولید­کننده و مصرف­ کننده message­ های message broker در نظر گرفت. در celery کلاینت را producer و worker را consumer می­ نامند. یک task یا message متشکل از header و body است که message payload یا body شامل دیتایی است که به سمت مصرف کننده هدایت می شود.اجزا و نحوه کارکرد Celeryدر انتها به معرفی اجزای Celery و شرح وظیفه هرکدام می پردازیم:تولیدکننده پیام (Producer):یک Producer کاربر اپلیکیشنی است که پیام­ها را ارسال می­کند.واسطه (Broker):پیام ها را از Producer دریافت می­کند و آن­ها را به سمت Consumer هدایت می­ کند. Broker می­تواند شامل یک یا چند صف باشد.تبادل (Exchange):یک Producer پیام­ها را از طریق تبادل (Exchange) ارسال می ­کند. Exchange ها پیام­ ها را دریافت می­ کنند و آن­ها را در صف­ ها قرار می­ دهند.صف (Queue):یک بافر است که پیام­ها در آن دخیره می­شوند.قید ها (Bindings):قوانین هستند که exchange­ ها برای مسیریابی از آنها استفاده می­کنند.کلیدهای مسیریابی (Routing Keys):اتصال ممکن است یک Routing Keys اختیاری داشته باشد که exchange ازآن برای انتقال پیام به صف استفاده کند.مصرف کننده پیام (Consumer):یک Consumer اپلیکیشنی است که پیام­ ها را دریافت کرده و آن­ها را پردازش می­کند.در این مقاله سعی کردم در حد آشنایی و به طور خلاصه به Celery بپردازم. برای مطاله بیشتر و نحوه پیاده سازی Celery در پروژه، به مستندات مراجعه کنید.</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Fri, 01 May 2020 00:22:25 +0430</pubDate>
            </item>
                    <item>
                <title>قواعد نام گذاری در برنامه نویسی</title>
                <link>https://virgool.io/fboard/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D9%86%D8%A7%D9%85-%DA%AF%D8%B0%D8%A7%D8%B1%DB%8C-%D8%AF%D8%B1-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-p0n6za6v1561</link>
                <description>یک برنامه نویس باید از قواعد وضع شده برای نوشتن کدهای تمیز و استاندارد استفاده کند. یکی از این قواعد نام گذاری متغیرها، کلاس ها، توابع، پکیج و سایر عناصر برنامه است.نام گذاری PascalCase:در این شیوه نام گذاری حرف اول همه کلمات با حروف بزرگ نوشته می شود و بین هر کلمه از هیج کاراکتری (space ،  - ، _ و ...) استفاده نمی شود. کاربرد در نامگذاری کلاس ها و property ها. مانند: ClientTarget, UserStatusنام گذاری camelCase:در این شیوه نام گذاری هر کلمه با حرف کوچک و سایر کلمات با حروف بزرگ نوشته می شود و بین هر کلمه از هیج کاراکتری (space ،  - ، _ و ...) استفاده نمی شود. کاربرد در نامگذاری پارامترهای ارسالی به تابع، متغیر ها و کلیدها در json.مانند: userId, deliveredAtTimeنام گذاری snake_case:در این شیوه نام گذاری هر کلمه با _ (underline) از کلمه قبلی جدا می شود. برای نامگذاری function, method, variable .مانند: user_id, received_atنام گذاری kebab-case: در این روش نام گذاری هر کلمه با - (dash) از کلمه قبلی جدا می شود. اسامی دیگه این سبک lisp-case, spinal-case, Train-Case. این نامگذاری تقریبا منسوخ شده است و برای query string در url مورد استفاده قرار می گیرد. سایر کاربرد های آن با نامگذاری snake case انجام می شود.مانند: lazy-load, fox-nameاستاندارد پایتون برای نامگذاری طبق استاندارد PEP8:نکات تکمیلی:استاندارد نامگذاری constant ها به صورت CONSTANT_NAME انجام می شود.از به کاربردن حروف مختصر اجتناب کنید (کلمات مختصر کاربرد خودشان را دارند مثلا استفاده از url یا id صحیح است).قبل از نام interface ها از I(حرف آی در انگلیسی) استفاده کنیم (مثلا ICar).نام فایل ها را همانند نام کلاس اصلی قرار دهیم.در  نام گذاری enum  از نام های مفرد استفاده کنیم.</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Mon, 23 Dec 2019 15:10:53 +0330</pubDate>
            </item>
                    <item>
                <title>مفاهیم RESTful API در ۲ دقیقه</title>
                <link>https://virgool.io/@mehdinazari/%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-restful-api-ev1krqkkfhko</link>
                <description>ابتدا به تعریف (Representational State Transfer) REST می پردازیم. REST یک معماری نرم‌افزاری برای پیاده سازی API هاست. این معماری مبتنی بر پروتکل HTTP است که پروتکلی بر اساس درخواست (Request) و پاسخ (Response) است. HTTP از متد های پیش فرض GET برای بازیابی اطلاعات، PUT برای به روز رسانی، POST برای ایجاد و  DELETE برای حذف کردن منابع به کار می رود. REST معروف ترین معماری برای تولید API هاست. از مزایای REST می توان به پیاده‌سازی سریع‎تر و توسعه ساده اشاره کرد.مجموعه ای از قواعد و مکانیزم ها که اپلیکیشن ها و یا کامپوننت های اپلیکیشن از طریق آن ها با هم ارتباط برقرار می کنند را API (Application Programming Interface) می گویند. API داده های مورد نیاز اپلیکیشن را از طریق فرمت JSON (JavaScript Object Notation) که فرمت کلید-مقدار (key-value) به خروجی ارسال می کند و از این طریق توسعه اپلیکیشن را ساده تر می کند. API جایگزین SOAP شده است که از فرمت XML برای ارسال خروجی استفاده می کرد. در حقیقت API به اپلیکیشن ها اجازه می‌دهد با یکدیگر گفت‌وگو کنند.بعد از درک کردن مفاهیم REST و API حال نوبت به تعریف RESTful است. RESTful یکی از معروف‌ترین معماری‌های مورد استفاده در توسعهٔ وب سرویس‌ها است و انعطاف بسیار زیادی را برای توسعه دهندگان به ارمغان آورده است. در حقیقت RESTful  را می‌توان مفسری برای REST دانست.تفاوت REST و RESTful APIدر حقیقت REST یک معماری است که امکان طراحی یک وب سرویس را به  روش خاصی در اختیار توسعه دهنده قرار می دهد اما RESTful API یک سرویس است که این معماری را  پیاده سازی کرده است. وب سرویس هایی که برپایه RESTful API ساخته میشوند، Stateless هستند به این معنی که به جای ذخیره‌سازی وضعیت کلاینت در سمت سرور، کلیهٔ داده‌ها در سمتِ خود  کلاینت ذخیره می‌شوند و در هر درخواستی نیز برای سرور ارسال می‌شوند. ویژگی‎های RESTful API:• کلاینت-سرور (Client-Server): در این معماری کلاینت به‌عنوان front-end و سرور به‌عنوان  back-end شناخته می‌شود. در این معماری حداقل وابستگی بین کلاینت و سرور  وجود دارد، این اصل  به توسعه دهنده ها اجازه می‌دهد تا بدون هیچ‌گونه وابستگی به  یکدیگر به توسعه اپلیکیشن بپردازند.• بدون وضعیت (Stateless): هیچ داده‎ای نباید در زمان پردازش انتقال درخواست روی سرور ذخیره شود و session باید در سمت کلاینت ذخیره شود. به عبارت دیگر، سرور هرگز نسبت به وضعیت  درخواست‌های قبلی کلاینت اطلاعی ندارد. یکی از مزیت‌های کلیدی Stateless آن است که  تغییرات صورت‌گرفته روی سرور هرگز کلاینت را با مشکل مواجه نمی‌کنند.•  قابل کش شدن (Cacheable): کلاینت باید قادر باشد که Response را به صورت Cache ذخیره کند.• یکپارچگی رابط (Uniform Interface): برای دستیابی به Method های مختلف  می‌باید از یک URL منحصر‌به‌فرد استفاده کرد به علاوه اینکه در Response می‌بایست با استفاده از Status code ها اطلاعات شفافی در اختیار کلاینت قرار دهیم.</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Fri, 13 Dec 2019 20:33:33 +0330</pubDate>
            </item>
                    <item>
                <title>چی به چی دسترسی داره (‌Access Modifier)</title>
                <link>https://virgool.io/@mehdinazari/%DA%86%DB%8C-%D8%A8%D9%87-%DA%86%DB%8C-%D8%AF%D8%B3%D8%AA%D8%B1%D8%B3%DB%8C-%D8%AF%D8%A7%D8%B1%D9%87-access-modifier-bbms5mlvp8ji</link>
                <description>سطوح دسترسی در برنامه نویسی یکی از اصول مهم و پایه ای به حساب می آید و دانستن آن برای نوشتن یک برنامه الزامی است. در واقع کنترل دسترسی (Access Modifire) مشخص می کند چگونه به یکclass، method، variable و یا property در برنامه دسترسی خواهیم داشت.انواع دسترسی یک عنصر به صورت زیر است:عمومی (public): این سطح دسترسی کمترین محدودیت را در انواع خود دارد، عناصری که به صورت public تعریف می شوند در تمامی کلاس ها به آن ها دسترسی خواهیم داشت.محافظت شده (protected):فقط اعضای کلاس و کلاس هایی که از آن کلاس ارث بری می کنند به عناصر private دسترسی دارند. خصوصی (private):فقط اعضای کلاس جاری به عناصر private دسترسی دارند. کلاس ها به طور پیش فرض private هستند.‌درونی (internal):عناصر فقط در پروژه فعلی در دستر هستند (فقط در زبان #C). درونی محافظت شده (protected internal):مانند دسترسی internal است با این تفاوت که این عناصر در پروژه های دیگر نیز در دسترس هستند (فقط در زبان #C).موارد گفته شده در اکثر زبان های برنامه نویسی در مشابه است ولی در مورد زبان پایتون اندکی متفاوت است. در ادامه به بررسی و پیاده سازی Access Modifier در پایتون می پردازیم.در پایتون تنها انواع public‌، private و protected را در اختیار داریم که بدون استفاده از کلمه کلیدی و به طور ضمنی پیاده سازی می شوند.به عنوان مثال کلاس زیر را در نظر بگیرید:class Client:
    def __init__(self, name, age):
        self.name = name
        self.age = ageدر تابع سارنده کلاس دو متغیر age و name تعریف شده است که به صورت پیش فرض public هستند و در همه کلاس های پروژه در دسترس هستند. حال از کلاس Client نمونه ایجاد می کنیم و مشاهده می کنیم که به عناصر عمومی دسترسی داریم:&gt;&gt;&gt; client = Client(&amp;quotmehdi&amp;quot,28)
&gt;&gt;&gt; client.name
mehdi
&gt;&gt;&gt; client.age
28در زبان پایتون عنصر protected به معنای گفته شده عملا وجود ندارد و به طور ضمنی برنامه نویس با قرار دادن یک ـ (underline) قبل از نام عناصر مشخص می کند که عنصر به صورت protected تعریف شده است. class Client:
    def __init__(self, name, age):
        self._name = name  
        self._age = age حال از کلاس نمونه می سازیم و همانطور که مشاهده می کنید همچنان به عناصر protected دسترسی داریم:&gt;&gt;&gt; client = Client(&amp;quotmehdi&amp;quot, 28)
&gt;&gt;&gt; client._age
28
&gt;&gt;&gt; client._age = 20
&gt;&gt;&gt; client._age
20راه حل دیگر استفاده از property به منظور protected کردن (کپسوله کردن) اعضای کلاس است. اما این روش نیز منجر به عدم دسترسی به اعضای protected  نمی شود. بنابراین می توان نتیجه گرفت که در پایتون، برنامه نویس مسئول عدم استفاده از فیلدهای protected است.class Client:
    def __init__(self, name):
        self._name = name  
    @property
    def name(self):
        return self._name
    @name.setter
    def name(new_name):
        self._name = new_name&gt;&gt;&gt; client = Client(&#039;name&#039;)
&gt;&gt;&gt; client.neme
&#039;name&#039;
&gt;&gt;&gt; client._name
&#039;name&#039;همانطور که متوجه شدیم، پایتون مکانیزمی جهت جلوگیری از instance variable ها و یا instance method ها ندارد و تنها به ارائه convention برای کنترل این اعضا بسنده می کند.برای تعریف عناصر private در پایتون از __ (۲ تا underline) قبل از نام عنصر استفاده می کنیم. class Client:
    def __init__(self, name, age):
        self.__name = name  
        self.__age = age با ایجاد نمونه از کلاس Client  و فراخوانی مقادیر private خواهیم داشت:&gt;&gt;&gt; client = Client(&amp;quotmehdi&amp;quot, 28)
&gt;&gt;&gt; client.__age
AttributeError: &#039;client&#039; object has no attribute &#039;__age&#039;خطای فوق نشان می دهد نمونه ساخته شده دسترسی به مقادیر private را نخواهد داشت.اما هنوز امکان دسترسی به متغیر های private وجود دارد. با در نظر داشتن مثال فوق به صورت زیر به age__ و ‌name__ دسترسی خواهیم داشت:&gt;&gt;&gt; client._Client__name
mehdi</description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Tue, 10 Dec 2019 10:54:55 +0330</pubDate>
            </item>
                    <item>
                <title>همه چیز درباره interpreter و compiler مختصر و مفید</title>
                <link>https://virgool.io/@mehdinazari/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-interpreter-%D9%88-compiler-i5cslxi1an1k</link>
                <description>انتخاب یک زبان برنامه نویسی برای استفاده در یک برنامه به فاکتور های زیادی بستگی داره که یکی از این فاکتورها نحوه اجرای برنامه با توجه به منابع موجود و سیتم عامل مورد استفاده است. خطایابی، انعطاف پذیری، محبوبیت نزد برنامه نویس (developer experience) و سرعت اجرای برنامه ویژگی های دیگری هستند که در انتخاب زبان موثر هستند. بسیاری از این موارد مستقیما به نحوه اجرای کدها وابسته هستند.زبان های برنامه نویسی از نظر نحوه اجرا به دو دسته تقسیم می شوند، زبان های تفسیری (interpreter) و زبان های ترجمه ای (compiler). در حقیقت هر دو روش گفته شده، زبان سطح بالا را به زبان قابل فهم برای ماشین (باینری) تبدیل می کنند.از زبان های کامپایلری می توان به c, c++, C#, cobol و visual basic اشاره کرد و python, javascript, php و ruby نمونه هایی از زبان های مفسری هستند.مهم ترین تفاوت بین interpreter و compiler در این است که تفسیر و اجرای کد ها در زبان های interpreter خط به خط صورت می گیرد و این روند در اجراهای بعدی نیز به همین صورت انجام می شود ولی در زبان های کامپایلری کدها به صورت کامل ترجمه شده و دفعات بعدی برنامه از روی کد ترجمه شده اجرا می شود.از آنجا که کد های نوشته شده به زبان های تفسیری هربار به صورت خط به خط اجرا می شوند نسبت به زبان های کامپایلری از منابع بیشتری استفاده می کنند و با سرعت کمتری نسبت به کد های کامپایل های شده اجرا می شوند ولی کامپایل اولیه نسبت به تفسیر  سرعت بسیار پایین تری خواهد داشت (مرحله کامپایل زمان بر است). به طور خلاصه می توان گفت اجرا برنامه در زبان های مفسری بسیار سریع تر از اجرای اول کد برنامه در زبان های کامپایلری است (به دلیل زمان بر بودن فرآیند کامپایل) ولی در اجراهای بعدی زبان های کامپایلری سریع تر هستند.برعکس زبان های مفسری، زبان های کامپایلری وابسته به سیستم عامل هستند یا اصطلاحا زبان های مفسری cross platform هستند. به این معنی که برنامه کامپایل شده در سیستم عامل در سیتم عامل دیگر قابل استفاده نیست و باید در همان سیستم عامل کامپایل شود. ولی در زبان های مفسری به شرط نصب بودن مفسر در سیستم عامل، برنامه در هر سیستم عاملی قابل اجرا خواهد بود.از دیگر مزیت زبان های مفسری نسبت به کامپایلری debug کردن و رفع خطای ساده برنامه به دلیل اجرای خط به خط برنامه است. </description>
                <category>مهدی نظری</category>
                <author>مهدی نظری</author>
                <pubDate>Fri, 06 Dec 2019 22:27:34 +0330</pubDate>
            </item>
            </channel>
</rss>