<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Cryo Learn</title>
    <link>https://cryo-networks.com/</link>
    <description>Cryo Learn آموزش‌های روشن و عملیِ برنامه‌نویسی دربارهٔ پایتون، جاوااسکریپت، گیت، SQL، لینوکس، CSS و الگوریتم‌ها منتشر می‌کند؛ برای یادگیرندگانی که می‌خواهند کدشان را واقعاً بفهمند.</description>
    <language>fa</language>
    <lastBuildDate>Thu, 29 Oct 2026 10:07:21 +0000</lastBuildDate>
    <atom:link href="https://cryo-networks.com/feed.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>گیت واقعاً چطور کار می‌کند: blob، tree، کامیت و ref</title>
      <link>https://cryo-networks.com/posts/git-internals-objects-refs/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/git-internals-objects-refs/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>گیت</category>
      <description>پوشهٔ .git را باز کنید و گیت را همان‌طور که هست ببینید: یک انبار اشیاء که هر شیء با هشِ محتوایش نام‌گذاری شده، به‌علاوهٔ چند اشاره‌گرِ جابه‌جاشدنی. یک کامیت را با دست بسازید و بالاخره rebase، reset و reflog را بفهمید.</description>
      <content:encoded>&lt;p&gt;بیشتر آدم‌ها گیت را به شکل فهرستی از دستورها یاد می‌گیرند که باید حفظ شوند. این روش جواب می‌دهد تا وقتی که چیزی خراب شود: یک rebase تاریخچه را طوری بازنویسی می‌کند که انتظارش را نداشتید، یک &lt;code&gt;reset --hard&lt;/code&gt; کار یک روزتان را «پاک» می‌کند، یا ناگهان در وضعیت detached HEAD هستید. آن‌وقت دستورها دیگر منطقی به نظر نمی‌رسند.&lt;/p&gt;
&lt;p&gt;در لایهٔ زیرین، گیت به‌طرز شگفت‌آوری ساده است. یک &lt;strong&gt;انبار کلید-مقدار از اشیاء تغییرناپذیر&lt;/strong&gt; است، به‌علاوهٔ چند &lt;strong&gt;اشاره‌گرِ جابه‌جاشدنی&lt;/strong&gt; که به آن‌ها ref می‌گویند. وقتی هر دو را با چشم خودتان ببینید، هر دستور گیت خلاصه می‌شود در «چند شیء اضافه کن، بعد یک اشاره‌گر را جابه‌جا کن».&lt;/p&gt;
&lt;p&gt;اگر با کار روزمره با برنچ‌ها راحت باشید، بیشترین بهره را از این مقاله می‌برید. اگر نه، اول &lt;a href=&#34;/posts/git-branching-workflow/&#34;&gt;روش کاری عملی با برنچ‌های گیت برای مبتدی‌ها&lt;/a&gt; را بخوانید.&lt;/p&gt;
&lt;h2 id=&#34;ذخیرهسازی-بر-اساس-محتوا&#34;&gt;ذخیره‌سازی بر اساس محتوا&lt;/h2&gt;
&lt;p&gt;گیت همه‌چیز (محتوای فایل‌ها، پوشه‌ها، کامیت‌ها) را به شکل &lt;strong&gt;شیء&lt;/strong&gt; (object) ذخیره می‌کند و نام هر شیء، هش SHA-1ِ محتوای آن است. از گیت بخواهید یک متن را هش کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;hash-object&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--stdin
ce013625030ba8dba906f756967f9e9ca394464a&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;این دستور را روی هر کامپیوتری و در هر مخزنی اجرا کنید، همین هش را می‌گیرید. گیت یک سرآیند کوچک (کلمهٔ &lt;code&gt;blob&lt;/code&gt;، یک فاصله، اندازه بر حسب بایت و یک بایت null) و بعد از آن محتوا را هش می‌کند، و شما می‌توانید بدون گیت هم همین را بازتولید کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;blob 6\0hello\n&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;sha1sum
ce013625030ba8dba906f756967f9e9ca394464a&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;-&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;این طراحی پیامدهای بزرگی دارد. محتوای یکسان فقط یک بار ذخیره می‌شود، هر چقدر هم که فایل‌ها یا کامیت‌های زیادی آن را داشته باشند. و چون نام به محتوا وابسته است، یک شیء هرگز نمی‌تواند تغییر کند: یک بایت را عوض کنید و یک شیء دیگر با یک نام دیگر خواهید داشت.&lt;/p&gt;
&lt;h2 id=&#34;چهار-نوع-شیء&#34;&gt;چهار نوع شیء&lt;/h2&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;نوع&lt;/th&gt;
&lt;th&gt;چه چیزی را ذخیره می‌کند&lt;/th&gt;
&lt;th&gt;به چه اشاره می‌کند&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;blob&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;محتوای یک فایل (بدون نام و بدون مجوزها)&lt;/td&gt;
&lt;td&gt;هیچ‌چیز&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;tree&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;یک پوشه: نام‌ها، حالت‌ها (mode) و هش ورودی‌هایش&lt;/td&gt;
&lt;td&gt;blobها و treeهای دیگر&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;commit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;یک عکس فوری: نویسنده، ثبت‌کننده، تاریخ و پیام&lt;/td&gt;
&lt;td&gt;یک tree و کامیت(های) والد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;tag&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;یک تگ annotated: سازندهٔ تگ، پیام و امضای اختیاری&lt;/td&gt;
&lt;td&gt;معمولاً یک کامیت&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;بیایید یک مخزن کوچک بسازیم و به اشیاء واقعی نگاه کنیم:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;init&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-b&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;demo&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;demo
mkdir&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;src
&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;# Demo&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;README.md
&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;print(&amp;quot;hello&amp;quot;)&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;src/app.py
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;.&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;commit&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-m&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;First commit&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;همین یک کامیت پنج شیء ساخت که به شکل فایل‌های فشرده زیر &lt;code&gt;.git/objects/&lt;/code&gt; ذخیره شده‌اند؛ نام پوشه دو کاراکتر اول هش است و نام فایل بقیهٔ آن:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;find&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;.git/objects&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-type&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;f
.git/objects/08/05455a24b6c68fbc38d0fa5d121f735984285d
.git/objects/11/b15b1a4584b08fa423a57964bdbf018b0da0d5
.git/objects/16/ae6a2afcc370fa1a06bc31edcacc3a7f2c41cc
.git/objects/60/546c2588e9d75d822392d6f296e1fd99f04c96
.git/objects/ef/6ad6746727fa1d0efcf4a020ec3caeda5ccf64&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition note&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;بیشتر هش‌های شما یکی خواهند بود&lt;/p&gt;
&lt;p&gt;blobها و treeها فقط به محتوا وابسته‌اند؛ پس اگر همین فایل‌ها را ساخته باشید، آن چهار هش روی کامپیوتر شما هم دقیقاً همین‌ها هستند. اما هش کامیت فرق می‌کند: نام، ایمیل و زمانِ دقیقِ شما در آن هست.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;خواندن-اشیاء-با-cat-file&#34;&gt;خواندن اشیاء با cat-file&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;git cat-file -p&lt;/code&gt; هر شیئی را خوانا چاپ می‌کند. از کامیتی شروع کنید که &lt;code&gt;HEAD&lt;/code&gt; به آن اشاره می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;cat-file&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;HEAD
tree&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;60546c2588e9d75d822392d6f296e1fd99f04c96
author&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Ada&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;lt;ada@example.com&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1793256281&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;+0000
committer&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Ada&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;lt;ada@example.com&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1793256281&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;+0000

First&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;commit&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;یک کامیت فقط چند خط متن است. دقیقاً به یک &lt;strong&gt;tree&lt;/strong&gt; اشاره می‌کند: عکس فوریِ کل پروژه. آن را دنبال کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;cat-file&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;60546c2
&lt;span class=&#34;m&#34;&gt;100644&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;blob&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;0805455a24b6c68fbc38d0fa5d121f735984285d&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;README.md
&lt;span class=&#34;m&#34;&gt;040000&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;tree&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;ef6ad6746727fa1d0efcf4a020ec3caeda5ccf64&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;src

$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;cat-file&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;ef6ad67
&lt;span class=&#34;m&#34;&gt;100644&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;blob&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;11b15b1a4584b08fa423a57964bdbf018b0da0d5&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;app.py

$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;cat-file&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;11b15b1
print&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;دقت کنید &lt;em&gt;نام&lt;/em&gt; فایل‌ها کجا نگه داشته می‌شود: در treeها، نه در blobها. تغییر نام یک فایل یک tree تازه می‌سازد اما از همان blob قبلی استفاده می‌کند.&lt;/p&gt;
&lt;p&gt;حالا یک فایل را تغییر دهید و دوباره کامیت کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;print(&amp;quot;hello, world&amp;quot;)&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;src/app.py
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;commit&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-am&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Greet the world&amp;quot;&lt;/span&gt;
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;cat-file&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;HEAD
tree&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;17b6cd9de955edb28d8a9b0e4668f588ba3c664a
parent&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;16ae6a2afcc370fa1a06bc31edcacc3a7f2c41cc
...
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;cat-file&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;HEAD^{tree}&amp;#39;&lt;/span&gt;
&lt;span class=&#34;m&#34;&gt;100644&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;blob&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;0805455a24b6c68fbc38d0fa5d121f735984285d&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;README.md
&lt;span class=&#34;m&#34;&gt;040000&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;tree&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;b6dcf64039da33b42fb025d2cc49c6d070c65686&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;src&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;کامیت جدید یک خط &lt;strong&gt;&lt;code&gt;parent&lt;/code&gt;&lt;/strong&gt; دارد که به کامیت اول اشاره می‌کند. tree ریشهٔ آن یک tree تازه برای &lt;code&gt;src&lt;/code&gt; دارد (چون &lt;code&gt;app.py&lt;/code&gt; تغییر کرده)، اما &lt;code&gt;README.md&lt;/code&gt; هنوز به همان blobِ قبلی، یعنی &lt;code&gt;0805455&lt;/code&gt;، اشاره می‌کند. فایل‌های تغییرنکرده هیچ هزینه‌ای ندارند.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;دو کامیت: دومی به والدش و به یک tree تازه اشاره می‌کند؛ blobِ README که تغییر نکرده بین هر دو tree مشترک است، و main و HEAD به جدیدترین کامیت اشاره می‌کنند&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;عکس فوری، نه تفاوت‌ها&lt;/p&gt;
&lt;p&gt;هر کامیت یک عکس فوریِ کامل (یک tree) ذخیره می‌کند، نه فهرستی از تغییرات. &lt;code&gt;git diff&lt;/code&gt; و &lt;code&gt;git show&lt;/code&gt; تغییرات را در لحظه و با مقایسهٔ دو tree محاسبه می‌کنند. برای صرفه‌جویی در فضای دیسک، &lt;code&gt;git gc&lt;/code&gt; بعداً اشیاء را در &lt;em&gt;packfile&lt;/em&gt;ها بسته‌بندی می‌کند و اشیاء مشابه را به شکل delta فشرده می‌کند؛ اما این فقط جزئیاتِ ذخیره‌سازی است و از دید بقیهٔ گیت پنهان است.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;refها-برنچها-فایلهای-۴۱-بایتی-هستند&#34;&gt;refها: برنچ‌ها فایل‌های ۴۱ بایتی هستند&lt;/h2&gt;
&lt;p&gt;اگر اشیاء هرگز تغییر نمی‌کنند، یک برنچ چطور «جلو می‌رود»؟ برنچ‌ها شیء نیستند؛ &lt;strong&gt;ref&lt;/strong&gt; هستند: فایل‌های کوچکی که یک هش کامیت را در خود دارند.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;cat&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;.git/HEAD
ref:&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;refs/heads/main

$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;cat&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;.git/refs/heads/main
ffb68609991f7ac36c595767d2d91545868364cb&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;HEAD&lt;/code&gt; معمولاً &lt;em&gt;نام&lt;/em&gt; برنچ فعلی را نگه می‌دارد و فایلِ برنچ یک هش کامیت را. وقتی کامیت می‌کنید، گیت اشیاء جدید را می‌نویسد و بعد همان یک فایلِ برنچ را با هش جدید بازنویسی می‌کند. از دید برنچ، کامیت کردن فقط همین است.&lt;/p&gt;
&lt;p&gt;این چند چیز را توضیح می‌دهد که در غیر این صورت جادو به نظر می‌رسند:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ساختن برنچ آنی است&lt;/strong&gt;، اندازهٔ مخزن هر چقدر که باشد: &lt;code&gt;git branch experiment&lt;/code&gt; فقط یک فایل ۴۱ بایتیِ تازه می‌نویسد. (گیت ممکن است بعداً refها را به یک فایل واحد به نام &lt;code&gt;.git/packed-refs&lt;/code&gt; منتقل کند که به همان شکل کار می‌کند.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;detached HEAD&lt;/strong&gt; یعنی &lt;code&gt;HEAD&lt;/code&gt; به‌جای &lt;code&gt;ref: refs/heads/...&lt;/code&gt; مستقیماً یک هش کامیت را در خود دارد. کامیت‌های جدید همچنان کار می‌کنند، اما هیچ برنچی جلو نمی‌رود که آن‌ها را به خاطر بسپارد.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;تگ‌ها&lt;/strong&gt; refهایی زیر &lt;code&gt;refs/tags/&lt;/code&gt; هستند که طبق قرارداد هرگز جابه‌جا نمی‌شوند.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;یک-کامیت-را-با-دست-بسازید&#34;&gt;یک کامیت را با دست بسازید&lt;/h2&gt;
&lt;p&gt;برای اینکه ثابت کنیم چیزی بیشتر از این در کار نیست، بیایید فایلی را بدون &lt;code&gt;git add&lt;/code&gt; و &lt;code&gt;git commit&lt;/code&gt; کامیت کنیم؛ فقط با دستورهای سطح پایین گیت که به آن‌ها «plumbing» می‌گویند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;c1&#34;&gt;# 1. Store the content as a blob (-w writes it into .git/objects)&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;blob&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Made without git add&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;hash-object&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-w&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--stdin&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# 2. Put it into the staging area (the index) under a file name&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;update-index&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--cacheinfo&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;100644&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$blob&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;NOTES.txt

&lt;span class=&#34;c1&#34;&gt;# 3. Turn the index into a tree object&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;tree&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;write-tree&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# 4. Create a commit object pointing to that tree, with HEAD as its parent&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;commit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;commit-tree&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$tree&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;HEAD&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-m&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Commit made by hand&amp;quot;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# 5. Move the branch pointer&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;update-ref&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;refs/heads/main&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$commit&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;log&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--oneline
8e0d264&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Commit&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;made&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;by&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;hand
ffb6860&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Greet&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;the&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;world
16ae6a2&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;First&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;commit&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;یک کامیت کاملاً معمولی. اگر حالا &lt;code&gt;git status&lt;/code&gt; را اجرا کنید، می‌بینید &lt;code&gt;NOTES.txt&lt;/code&gt; حذف‌شده نشان داده می‌شود: این فایل در کامیت و در index هست، اما ما هرگز آن را در پوشهٔ کاری ننوشتیم. &lt;code&gt;git restore NOTES.txt&lt;/code&gt; این را درست می‌کند. این‌ها سه جایی هستند که یک فایل در گیت می‌تواند باشد: &lt;strong&gt;پایگاه دادهٔ اشیاء&lt;/strong&gt;، &lt;strong&gt;index&lt;/strong&gt; و &lt;strong&gt;پوشهٔ کاری&lt;/strong&gt; شما.&lt;/p&gt;
&lt;h2 id=&#34;اینها-چه-چیزهایی-را-توضیح-میدهند&#34;&gt;این‌ها چه چیزهایی را توضیح می‌دهند&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;rebase کامیت‌های جدید می‌سازد.&lt;/strong&gt; هش هر کامیت، هش والدش را هم در بر می‌گیرد. وقتی یک برنچ را rebase می‌کنید، هر کامیت والد تازه‌ای می‌گیرد؛ پس گیت مجبور است کامیت‌های کاملاً جدید با هش‌های جدید بسازد، حتی اگر تغییرات کد یکسان باشند. کامیت‌های قدیمی هنوز وجود دارند؛ فقط برنچ حالا به جای دیگری اشاره می‌کند. به همین دلیل rebase کردنِ کامیت‌هایی که دیگران قبلاً pull کرده‌اند دردسر می‌سازد: آن‌ها هنوز کامیت‌های قدیمی را دارند.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;reset&lt;/code&gt; فقط یک اشاره‌گر را جابه‌جا می‌کند.&lt;/strong&gt; &lt;code&gt;git reset --hard HEAD~2&lt;/code&gt; برنچ فعلی را دو کامیت عقب می‌برد (و فایل‌های شما را هم با آن هماهنگ می‌کند). خودِ کامیت‌ها پاک نمی‌شوند.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;reflog به خاطر دارد اشاره‌گرها کجا بوده‌اند.&lt;/strong&gt; هر بار که &lt;code&gt;HEAD&lt;/code&gt; یا یک برنچ جابه‌جا می‌شود، گیت آن را ثبت می‌کند. پس یک کامیتِ «گم‌شده» معمولاً فقط یک دستور با شما فاصله دارد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;reset&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--hard&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;HEAD~2&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# oops&lt;/span&gt;
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;reflog
16ae6a2&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;HEAD@&lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;:&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;reset:&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;moving&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;to&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;HEAD~2
8e0d264&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;HEAD@&lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;:&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;...
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;reset&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--hard&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;8e0d264&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# or: git branch rescue 8e0d264&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;این تور ایمنی تاریخ انقضا دارد&lt;/p&gt;
&lt;p&gt;کامیت‌هایی که هیچ برنچ، تگ یا ورودیِ reflogی به آن‌ها نمی‌رسد، بالاخره توسط &lt;code&gt;git gc&lt;/code&gt; پاک می‌شوند. به‌طور پیش‌فرض ورودی‌های reflog برای کامیت‌های دست‌نیافتنی بعد از ۳۰ روز منقضی می‌شوند (و برای بقیه بعد از ۹۰ روز). کار گم‌شده را زود بازیابی کنید و هرگز فرض نکنید کامیتی که push نشده تا ابد امن است.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;یکپارچگی در خودِ ساختار است.&lt;/strong&gt; چون هش هر کامیت tree آن را پوشش می‌دهد و هش هر tree، blobهایش را، یک هش کامیت ضامنِ کل تاریخچهٔ پشت سرش است. یک بایت را در هر جای گذشته عوض کنید تا همهٔ هش‌های بعد از آن عوض شوند. (گیت دقیقاً به همین دلیل به‌تدریج از SHA-1 به SHA-256 مهاجرت می‌کند؛ همین حالا هم می‌توانید آن را با &lt;code&gt;git init --object-format=sha256&lt;/code&gt; امتحان کنید.)&lt;/p&gt;
&lt;h2 id=&#34;دستورهای-plumbing-ارزشمند&#34;&gt;دستورهای plumbingِ ارزشمند&lt;/h2&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;دستور&lt;/th&gt;
&lt;th&gt;چه کاری می‌کند&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git cat-file -t &amp;lt;obj&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;نوع یک شیء را نشان می‌دهد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git cat-file -p &amp;lt;obj&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;یک شیء را خوانا چاپ می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git ls-tree -r HEAD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;همهٔ فایل‌های tree یک کامیت را به‌صورت بازگشتی فهرست می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git rev-parse main&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;یک نام (برنچ، تگ، &lt;code&gt;HEAD~2&lt;/code&gt;…) را به هش تبدیل می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git hash-object -w &amp;lt;file&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;یک فایل را به‌عنوان blob ذخیره می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git update-ref &amp;lt;ref&amp;gt; &amp;lt;hash&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;یک ref را به یک کامیت اشاره می‌دهد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git count-objects -vH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;نشان می‌دهد چند شیء وجود دارد و چقدر فضا گرفته‌اند&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;گیت یک &lt;strong&gt;انبار اشیاء بر اساس محتوا&lt;/strong&gt; است: نام هر شیء هش محتوای آن است، پس اشیاء هرگز تغییر نمی‌کنند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;blobها&lt;/strong&gt; محتوای فایل‌ها را نگه می‌دارند، &lt;strong&gt;treeها&lt;/strong&gt; پوشه‌ها و نام‌ها را، و &lt;strong&gt;کامیت‌ها&lt;/strong&gt; به یک tree و والد(های) خود اشاره می‌کنند.&lt;/li&gt;
&lt;li&gt;کامیت‌ها &lt;strong&gt;عکس فوری&lt;/strong&gt; هستند؛ فایل‌های تغییرنکرده به‌رایگان بین آن‌ها مشترک‌اند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;برنچ‌ها، تگ‌ها و HEAD همه ref هستند&lt;/strong&gt;: فایل‌های کوچکی که یک هش یا نامِ یک ref دیگر را در خود دارند.&lt;/li&gt;
&lt;li&gt;rebase، reset و amend &lt;strong&gt;اشیاء جدید می‌سازند و اشاره‌گرها را جابه‌جا می‌کنند&lt;/strong&gt;. تاریخچه را در جا ویرایش نمی‌کنند، و به همین دلیل &lt;strong&gt;reflog&lt;/strong&gt; معمولاً می‌تواند همه‌چیز را برگرداند.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;دفعهٔ بعد که یک دستور گیت غافلگیرتان کرد، دو سؤال بپرسید: &lt;em&gt;چه اشیائی ساخت، و کدام اشاره‌گر را جابه‌جا کرد؟&lt;/em&gt;&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>پروسس‌های لینوکس از درون: fork، exec، سیگنال‌ها و زامبی‌ها</title>
      <link>https://cryo-networks.com/posts/linux-processes-signals/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/linux-processes-signals/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>لینوکس</category>
      <description>وقتی یک دستور را اجرا می‌کنید واقعاً چه اتفاقی می‌افتد: fork و exec، کدهای خروج و wait، اینکه سیگنال‌ها چطور برنامه‌ها را متوقف می‌کنند (و چطور مؤدبانه خاموش شویم)، زامبی‌ها از کجا می‌آیند و چرا PID 1 در کانتینر Ctrl+C شما را نادیده می‌گیرد.</description>
      <content:encoded>&lt;p&gt;&lt;code&gt;ls&lt;/code&gt; را تایپ می‌کنید و &lt;kbd&gt;Enter&lt;/kbd&gt; را می‌زنید. فهرستی از فایل‌ها ظاهر می‌شود و اعلانِ خط فرمان برمی‌گردد. پشت این ماجرا، کرنل یک پروسس ساخته، برنامه‌اش را عوض کرده، وضعیتِ خروجش را جمع کرده و بعد از آن تمیزکاری کرده؛ فقط با چند فراخوانیِ سیستمی که همهٔ برنامه‌های لینوکس به آن‌ها تکیه دارند.&lt;/p&gt;
&lt;p&gt;دانستنِ این فراخوانی‌ها خیلی چیزها را توضیح می‌دهد که در غیر این صورت مرموز به نظر می‌رسند: چرا &lt;code&gt;cd&lt;/code&gt; نمی‌تواند یک برنامهٔ بیرونی باشد، کد خروج ۱۳۷ چه معنایی دارد، چرا &lt;code&gt;kill -9&lt;/code&gt; باید آخرین چاره‌تان باشد، پروسس‌های زامبی از کجا می‌آیند و چرا یک کانتینر گاهی دقیقاً ده ثانیه &lt;code&gt;docker stop&lt;/code&gt; را نادیده می‌گیرد. مثال‌ها از ماژول &lt;code&gt;os&lt;/code&gt; پایتون استفاده می‌کنند که تقریباً یک‌به‌یک به فراخوانی‌های سیستمیِ زیرین نگاشت می‌شود، به‌علاوهٔ ابزارهای استانداردی مثل &lt;code&gt;ps&lt;/code&gt;. اگر چند اسکریپت شل نوشته باشید بهرهٔ بیشتری می‌برید؛ &lt;a href=&#34;/posts/bash-scripts-that-dont-break/&#34;&gt;نوشتن اسکریپت‌های Bash که خراب نمی‌شوند&lt;/a&gt; را ببینید.&lt;/p&gt;
&lt;h2 id=&#34;فراخوانیهای-fork-و-exec-هر-برنامهای-اینطور-شروع-میشود&#34;&gt;فراخوانی‌های fork و exec: هر برنامه‌ای این‌طور شروع می‌شود&lt;/h2&gt;
&lt;p&gt;لینوکس پروسس‌های جدید را در دو مرحلهٔ جدا می‌سازد:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;fork()&lt;/code&gt;&lt;/strong&gt; یک کپی از پروسسِ فراخواننده می‌سازد. والد و فرزند از همان خطِ کد ادامه می‌دهند، با همان محتوای حافظه، فایل‌های باز و متغیرهای محیطی. تنها تفاوت، مقدارِ بازگشتیِ &lt;code&gt;fork()&lt;/code&gt; است: در فرزند &lt;code&gt;0&lt;/code&gt; و در والد، PID فرزند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;exec()&lt;/code&gt;&lt;/strong&gt; برنامه‌ای را که در پروسسِ فعلی اجرا می‌شود با یک برنامهٔ جدید جایگزین می‌کند. PID همان می‌ماند؛ کد، حافظه و پشته دور ریخته می‌شوند و از فایل اجراییِ جدید از نو بارگذاری می‌شوند.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;شل &lt;code&gt;ls&lt;/code&gt; را این‌طور اجرا می‌کند: خودش را fork می‌کند، بعد &lt;strong&gt;فرزند&lt;/strong&gt; &lt;code&gt;ls&lt;/code&gt; را exec می‌کند و &lt;strong&gt;والد&lt;/strong&gt; منتظر می‌ماند. همین کار در پایتون:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;

&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;parent: my PID is &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getpid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;flush&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Child: a copy of the parent. Replace it with the `ls` program.&lt;/span&gt;
    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;child:  my PID is &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getpid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;, my parent is &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getppid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;flush&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execvp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;ls&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;ls&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;-d&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;/tmp&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;never printed: exec only returns if it fails&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Parent: wait for the child and collect its exit status.&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;waitpid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;parent: child &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; exited with code &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;waitstatus_to_exitcode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$ python3 forkexec.py
parent: my PID is 726920
child:  my PID is 726922, my parent is 726920
/tmp
parent: child 726922 exited with code 0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition note&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;چرا flush=True مهم است&lt;/p&gt;
&lt;p&gt;&lt;code&gt;exec&lt;/code&gt; کلِ برنامه را جایگزین می‌کند، از جمله بافرِ خروجیِ پایتون را. اگر خروجی به یک پایپ یا فایل برود بافر می‌شود، و هر چیزی که هنوز flush نشده بی‌صدا از دست می‌رود. همین برای &lt;code&gt;printf&lt;/code&gt; زبان C هم صدق می‌کند. قبل از fork یا exec، خروجی را flush کنید.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;جدا بودنِ این دو فراخوانی همان چیزی است که شل‌های یونیکس را این‌قدر انعطاف‌پذیر می‌کند. بین &lt;code&gt;fork&lt;/code&gt; و &lt;code&gt;exec&lt;/code&gt;، فرزند هنوز کدِ شل را اجرا می‌کند؛ پس می‌تواند اول محیطِ خودش را مرتب کند: توصیف‌گرهای فایل (file descriptor) را برای &lt;code&gt;&amp;gt; file&lt;/code&gt; یا &lt;code&gt;|&lt;/code&gt; جابه‌جا کند، پوشه را عوض کند و متغیرهای محیطی را تنظیم کند. بعد برنامه را exec می‌کند که همهٔ این‌ها را به ارث می‌برد.&lt;/p&gt;
&lt;p&gt;این همچنین توضیح می‌دهد چرا &lt;code&gt;cd&lt;/code&gt; باید یک &lt;strong&gt;دستورِ داخلیِ شل&lt;/strong&gt; (builtin) باشد. یک پروسسِ فرزند فقط می‌تواند پوشهٔ کاریِ خودش را عوض کند، و این تغییر با خارج شدنش از بین می‌رود. برای عوض کردنِ پوشهٔ &lt;em&gt;خودِ شل&lt;/em&gt;، شل باید خودش این کار را بکند.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;زندگیِ یک پروسس: شل (PID 4100) یک فرزند (PID 4101) را fork می‌کند، فرزند ls را exec می‌کند، ls با کد ۰ خارج می‌شود، فرزند تا وقتی شل wait را صدا بزند زامبی می‌ماند و بعد ناپدید می‌شود&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&#34;کدهای-خروج-و-wait&#34;&gt;کدهای خروج و wait&lt;/h2&gt;
&lt;p&gt;وقتی یک پروسس تمام می‌شود، یک &lt;strong&gt;وضعیتِ خروج&lt;/strong&gt; (exit status) برای والدش باقی می‌گذارد: طبق قرارداد ۰ برای موفقیت و ۱ تا ۲۵۵ برای شکست. والد آن را با &lt;code&gt;wait()&lt;/code&gt; یا &lt;code&gt;waitpid()&lt;/code&gt; جمع می‌کند و شل آن را در &lt;code&gt;$?&lt;/code&gt; می‌گذارد.&lt;/p&gt;
&lt;p&gt;اگر پروسس با یک &lt;strong&gt;سیگنال&lt;/strong&gt; کشته شده باشد، شل &lt;code&gt;128 + شمارهٔ سیگنال&lt;/code&gt; را گزارش می‌کند. این‌ها مدام در لاگ‌ها و خروجیِ CI دیده می‌شوند:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;کد خروج&lt;/th&gt;
&lt;th&gt;معنی&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;موفقیت&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;، &lt;code&gt;2&lt;/code&gt;، …&lt;/td&gt;
&lt;td&gt;برنامه خطایی گزارش کرده (معنایش در هر برنامه فرق می‌کند)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;126&lt;/code&gt; / &lt;code&gt;127&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;دستور پیدا شد اما اجرایی نیست / دستور پیدا نشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;130&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;با SIGINT (۲) کشته شد: کسی &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;C&lt;/kbd&gt; را زد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;137&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;با SIGKILL (۹) کشته شد: اغلب &lt;strong&gt;OOM killer&lt;/strong&gt; (قاتلِ کمبود حافظه)، یا کانتینری که از سقف حافظه‌اش فراتر رفته&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;143&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;با SIGTERM (۱۵) کشته شد: یک درخواستِ عادیِ خاموش شدن، مثلاً &lt;code&gt;docker stop&lt;/code&gt; یا یک دیپلوی&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;سیگنالها-خبر-دادن-به-یک-پروسس&#34;&gt;سیگنال‌ها: خبر دادن به یک پروسس&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;سیگنال&lt;/strong&gt; یک اعلانِ کوچک و ناهمگام است که کرنل یا پروسسِ دیگری (با &lt;code&gt;kill&lt;/code&gt;) به یک پروسس می‌فرستد. با وجود اسمش، &lt;code&gt;kill&lt;/code&gt; &lt;em&gt;هر&lt;/em&gt; سیگنالی را می‌فرستد؛ SIGTERM فقط پیش‌فرض است. آن‌هایی که بیشتر می‌بینید:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;سیگنال&lt;/th&gt;
&lt;th&gt;شماره&lt;/th&gt;
&lt;th&gt;رفتار پیش‌فرض&lt;/th&gt;
&lt;th&gt;منبع معمول&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SIGHUP&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;پایان دادن&lt;/td&gt;
&lt;td&gt;ترمینال بسته شده؛ خیلی از دیمن‌ها با آن تنظیماتشان را دوباره بارگذاری می‌کنند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIGINT&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;پایان دادن&lt;/td&gt;
&lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;C&lt;/kbd&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIGQUIT&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;پایان دادن + core dump&lt;/td&gt;
&lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;\&lt;/kbd&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIGKILL&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;پایان دادن، &lt;strong&gt;قابل گرفتن نیست&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kill -9&lt;/code&gt;، OOM killer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIGTERM&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;پایان دادن&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kill&lt;/code&gt;، &lt;code&gt;systemctl stop&lt;/code&gt;، &lt;code&gt;docker stop&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIGCHLD&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;نادیده گرفتن&lt;/td&gt;
&lt;td&gt;یک پروسسِ فرزند خارج یا متوقف شده&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIGSTOP / SIGTSTP&lt;/td&gt;
&lt;td&gt;19 / 20&lt;/td&gt;
&lt;td&gt;مکث&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kill -STOP&lt;/code&gt; / &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Z&lt;/kbd&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;(شماره‌ها مربوط به لینوکس روی x86 و ARM هستند؛ برای دیدنِ فهرست کامل روی سیستم خودتان &lt;code&gt;kill -l&lt;/code&gt; را اجرا کنید.)&lt;/p&gt;
&lt;p&gt;یک پروسس می‌تواند بیشترِ سیگنال‌ها را با تابعِ خودش &lt;strong&gt;مدیریت&lt;/strong&gt; کند یا نادیده بگیرد. دو سیگنال هرگز قابل گرفتن یا نادیده گرفتن نیستند: &lt;strong&gt;SIGKILL&lt;/strong&gt; و &lt;strong&gt;SIGSTOP&lt;/strong&gt;. کرنل مستقیماً روی آن‌ها عمل می‌کند.&lt;/p&gt;
&lt;h2 id=&#34;خاموش-شدن-مؤدبانه&#34;&gt;خاموش شدنِ مؤدبانه&lt;/h2&gt;
&lt;p&gt;به همین دلیل باید &lt;strong&gt;اول SIGTERM&lt;/strong&gt; بفرستید و SIGKILL را فقط به‌عنوان آخرین چاره به کار ببرید. SIGTERM اجازه می‌دهد برنامه درخواستی را که در حال پاسخ دادن به آن است تمام کند، داده‌ها را روی دیسک بنویسد، اتصال‌های پایگاه داده را ببندد و فایل‌های قفل را پاک کند. SIGKILL آن را وسطِ یک دستورالعمل متوقف می‌کند، بدون هیچ فرصتی برای تمیزکاری.&lt;/p&gt;
&lt;p&gt;مدیریتِ SIGTERM چند خط بیشتر نیست:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;signal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;running&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;stop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;signum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;frame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;running&lt;/span&gt;
    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;got &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;signal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Signals&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;signum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;, finishing the current job...&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;flush&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;running&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;signal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;signal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;signal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SIGTERM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;running&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;        &lt;span class=&#34;c1&#34;&gt;# pretend to work&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;clean exit&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;flush&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$ python3 worker.py &amp;amp;
$ kill %1
got SIGTERM, finishing the current job...
clean exit&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;تابعِ مدیریت‌کننده فقط یک پرچم را تنظیم می‌کند؛ حلقهٔ اصلی آن را بررسی می‌کند و در یک نقطهٔ امن خارج می‌شود. انجام دادنِ کارِ واقعی داخلِ یک signal handler پرخطر است، چون می‌تواند برنامهٔ شما را هر جایی قطع کند. اسکریپت‌های Bash همین توانایی را با &lt;code&gt;trap &#39;cleanup&#39; TERM&lt;/code&gt; دارند.&lt;/p&gt;
&lt;p&gt;مدیرهای سرویس هم از همین الگو پیروی می‌کنند: &lt;code&gt;systemctl stop&lt;/code&gt; سیگنال SIGTERM می‌فرستد، صبر می‌کند (به‌طور پیش‌فرض ۹۰ ثانیه) و بعد SIGKILL می‌فرستد. &lt;code&gt;docker stop&lt;/code&gt; همین کار را با یک مهلتِ ۱۰ ثانیه‌ای انجام می‌دهد.&lt;/p&gt;
&lt;h2 id=&#34;زامبیها&#34;&gt;زامبی‌ها&lt;/h2&gt;
&lt;p&gt;وقتی یک فرزند خارج می‌شود، کرنل هنوز نمی‌تواند آن را کاملاً دور بریزد: ممکن است والد هنوز وضعیتِ خروجش را بخواهد. پس پروسس به یک &lt;strong&gt;زامبی&lt;/strong&gt; تبدیل می‌شود. دیگر حافظه یا فایلِ بازی ندارد، فقط یک ورودی در جدول پروسس‌ها که PID و وضعیتِ خروجش را نگه می‌دارد و منتظر است والد &lt;code&gt;wait()&lt;/code&gt; را صدا بزند. به جمع‌آوریِ این وضعیت &lt;strong&gt;درو کردن&lt;/strong&gt; (reaping) می‌گویند و زامبی را حذف می‌کند.&lt;/p&gt;
&lt;p&gt;والدی که هرگز &lt;code&gt;wait()&lt;/code&gt; را صدا نمی‌زند، زامبی‌ها را پشت سر جا می‌گذارد. بیایید یکی بسازیم:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# the child exits immediately...&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;child PID: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;           &lt;span class=&#34;c1&#34;&gt;# ...but the parent never calls wait()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$ python3 zombie.py &amp;amp;
child PID: 726905
$ ps -o pid,ppid,stat,cmd --ppid $!
    PID    PPID STAT CMD
 726905  726903 Z    [python3] &amp;lt;defunct&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;حرف &lt;code&gt;Z&lt;/code&gt; در ستونِ &lt;code&gt;STAT&lt;/code&gt; و عبارتِ &lt;code&gt;&amp;lt;defunct&amp;gt;&lt;/code&gt; نشانهٔ زامبی‌اند. چند زامبی بی‌خطرند، اما هر کدام یک PID را اشغال می‌کنند، و یک سرورِ باگ‌دار که زامبی نشت می‌دهد در نهایت می‌تواند سقفِ PIDها را پر کند؛ از آن لحظه هیچ چیزی روی آن ماشین نمی‌تواند پروسسِ جدیدی شروع کند.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;نمی‌توانید یک زامبی را بکُشید&lt;/strong&gt;: از قبل مرده است، پس سیگنال‌ها اثری ندارند. والد را درست کنید تا &lt;code&gt;wait()&lt;/code&gt; را صدا بزند، یا والد را متوقف کنید. وقتی یک والد می‌میرد، فرزندانش (زنده یا زامبی) &lt;strong&gt;به PID 1 سپرده می‌شوند&lt;/strong&gt; (یا به نزدیک‌ترین پروسسی که به‌عنوان «subreaper» علامت خورده)، و آن پروسس خودکار آن‌ها را درو می‌کند. روی یک سیستمِ معمولی PID 1 همان &lt;code&gt;systemd&lt;/code&gt; است و در درو کردن خیلی خوب عمل می‌کند.&lt;/p&gt;
&lt;h2 id=&#34;پروسس-pid-1-خاص-است-و-کانتینرها-آن-را-به-مشکل-شما-تبدیل-میکنند&#34;&gt;پروسسِ PID 1 خاص است، و کانتینرها آن را به مشکلِ شما تبدیل می‌کنند&lt;/h2&gt;
&lt;p&gt;داخل یک کانتینر &lt;code&gt;systemd&lt;/code&gt;ی وجود ندارد. هر دستوری که ایمیج اجرا می‌کند، در PID namespace کانتینر &lt;strong&gt;PID 1&lt;/strong&gt; می‌شود، و PID 1 دو مسئولیتِ اضافه دارد:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;کرنل رفتارهای پیش‌فرضِ سیگنال را روی آن اعمال نمی‌کند.&lt;/strong&gt; سیگنالی که PID 1 برایش handler نصب نکرده باشد به‌سادگی نادیده گرفته می‌شود. برنامهٔ معمولی‌ای که به رفتارِ پیش‌فرضِ «پایان دادن»ِ SIGTERM تکیه دارد، &lt;strong&gt;&lt;code&gt;docker stop&lt;/code&gt; را نادیده می‌گیرد&lt;/strong&gt;، ده ثانیهٔ مهلت را همان‌جا می‌نشیند و بعد با SIGKILL کشته می‌شود.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;همهٔ یتیم‌ها را به ارث می‌برد&lt;/strong&gt;؛ پس باید آن‌ها را درو کند، وگرنه زامبی‌ها انباشته می‌شوند.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;اولی را بدون Docker هم می‌توانید ببینید. &lt;code&gt;unshare&lt;/code&gt; یک برنامه را به‌عنوان PID 1 در یک PID namespace تازه اجرا می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;sudo&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;unshare&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--fork&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--pid&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--mount-proc&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;python3&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-c&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;import time; time.sleep(30)&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt;
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;pid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;pgrep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-n&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-f&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;time.sleep&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# the Python process, as seen from outside&lt;/span&gt;
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;sudo&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;kill&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-TERM&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$pid&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;             &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# nothing happens: PID 1 has no SIGTERM handler&lt;/span&gt;
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;sudo&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;kill&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-KILL&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$pid&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;             &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# this works: SIGKILL from the parent namespace&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;راه‌حل‌ها ساده‌اند:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;یک پروسسِ init کوچک را به‌عنوان PID 1 اجرا کنید: &lt;code&gt;docker run --init&lt;/code&gt; ابزار &lt;a href=&#34;https://github.com/krallin/tini&#34;&gt;tini&lt;/a&gt; را اضافه می‌کند که سیگنال‌ها را به برنامهٔ شما می‌رساند و زامبی‌ها را درو می‌کند. کاربرانِ Kubernetes می‌توانند &lt;code&gt;tini&lt;/code&gt; (یا &lt;code&gt;dumb-init&lt;/code&gt;) را به‌عنوان entrypoint به ایمیج اضافه کنند.&lt;/li&gt;
&lt;li&gt;کاری کنید برنامه‌تان SIGTERM را صریحاً مدیریت کند، مثل &lt;code&gt;worker.py&lt;/code&gt; در بالا.&lt;/li&gt;
&lt;li&gt;در Dockerfile از &lt;strong&gt;شکلِ exec&lt;/strong&gt; استفاده کنید، یعنی &lt;code&gt;CMD [&#34;python3&#34;, &#34;app.py&#34;]&lt;/code&gt;، نه &lt;code&gt;CMD python3 app.py&lt;/code&gt;. شکلِ shell دستورِ &lt;code&gt;/bin/sh -c &#34;python3 app.py&#34;&lt;/code&gt; را اجرا می‌کند؛ پس &lt;em&gt;شل&lt;/em&gt; PID 1 می‌شود و SIGTERM را به برنامهٔ شما نمی‌رساند.&lt;/li&gt;
&lt;li&gt;اسکریپت‌های entrypoint را با &lt;strong&gt;&lt;code&gt;exec &#34;$@&#34;&lt;/code&gt;&lt;/strong&gt; تمام کنید. &lt;code&gt;exec&lt;/code&gt; شل را با برنامهٔ شما جایگزین می‌کند (همان exec بالا)؛ پس برنامه‌تان PID 1 می‌شود و سیگنال‌ها را مستقیماً دریافت می‌کند.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;بررسی-پروسسها&#34;&gt;بررسیِ پروسس‌ها&lt;/h2&gt;
&lt;p&gt;هر پروسس یک پوشه زیرِ &lt;strong&gt;&lt;code&gt;/proc/&amp;lt;PID&amp;gt;/&lt;/code&gt;&lt;/strong&gt; دارد و بیشترِ ابزارها فقط از آن می‌خوانند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;ps&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-eo&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;pid,ppid,stat,etime,cmd&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--forest&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# every process, as a tree&lt;/span&gt;
pstree&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt;                                 &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# a compact tree with PIDs&lt;/span&gt;
cat&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/proc/1234/status&lt;span class=&#34;w&#34;&gt;                     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# state, parent, memory, threads, signal masks&lt;/span&gt;
tr&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;lt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/proc/1234/cmdline&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# the full command line&lt;/span&gt;
ls&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-l&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/proc/1234/fd&lt;span class=&#34;w&#34;&gt;                       &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# open files, sockets and pipes&lt;/span&gt;
cat&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/proc/1234/environ&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;tr&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# its environment (needs permission)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;حرفِ اولِ ستونِ &lt;code&gt;STAT&lt;/code&gt; می‌گوید یک پروسس مشغول چه کاری است:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;وضعیت&lt;/th&gt;
&lt;th&gt;معنی&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;R&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;در حال اجرا، یا آمادهٔ اجرا&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;S&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;خواب، منتظرِ چیزی (بیشترِ پروسس‌ها، بیشترِ وقت‌ها)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;D&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;خوابِ وقفه‌ناپذیر، معمولاً منتظرِ دیسک یا ذخیره‌سازِ شبکه‌ای؛ حتی SIGKILL هم تا برگشتنش صبر می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;T&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;متوقف‌شده (SIGSTOP، &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Z&lt;/kbd&gt; یا یک دیباگر)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;زامبی: خارج شده و منتظرِ درو شدن است&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;پروسسی که در وضعیتِ &lt;code&gt;D&lt;/code&gt; گیر کرده و کشته نمی‌شود، تقریباً همیشه نشان‌دهندهٔ یک مشکلِ ذخیره‌سازی است (یک NFS mount هنگ‌کرده، یک دیسکِ در حال خرابی)، نه مشکلی در خودِ برنامه.&lt;/p&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;پروسس‌های جدید با &lt;strong&gt;&lt;code&gt;fork()&lt;/code&gt;&lt;/strong&gt; (کپی از پروسس فعلی) و &lt;strong&gt;&lt;code&gt;exec()&lt;/code&gt;&lt;/strong&gt; (جایگزین کردنِ برنامه‌اش) ساخته می‌شوند. فاصلهٔ بین این دو جایی است که شل‌ها redirect و پایپ‌ها را آماده می‌کنند.&lt;/li&gt;
&lt;li&gt;والد وضعیتِ خروج را با &lt;strong&gt;&lt;code&gt;wait()&lt;/code&gt;&lt;/strong&gt; جمع می‌کند؛ کدهای خروجِ بالای ۱۲۸ یعنی «با سیگنالِ (کد − ۱۲۸) کشته شد»: &lt;strong&gt;130&lt;/strong&gt; یعنی Ctrl+C، &lt;strong&gt;137&lt;/strong&gt; یعنی SIGKILL/OOM و &lt;strong&gt;143&lt;/strong&gt; یعنی SIGTERM.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SIGTERM&lt;/strong&gt; بفرستید و به برنامه‌ها فرصتِ خاموش شدن بدهید؛ &lt;strong&gt;SIGKILL&lt;/strong&gt; قابل گرفتن نیست و همهٔ تمیزکاری‌ها را رد می‌کند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;زامبی‌ها&lt;/strong&gt; فرزندانِ خارج‌شده‌ای هستند که کسی درویشان نکرده؛ والد را درست کنید یا بکُشید، نه زامبی را.&lt;/li&gt;
&lt;li&gt;در کانتینرها، &lt;strong&gt;PID 1&lt;/strong&gt; سیگنال‌هایی را که مدیریت نمی‌کند نادیده می‌گیرد و باید یتیم‌ها را درو کند: از &lt;code&gt;--init&lt;/code&gt;/tini، &lt;code&gt;CMD&lt;/code&gt; به شکلِ exec و &lt;code&gt;exec &#34;$@&#34;&lt;/code&gt; در entrypointها استفاده کنید.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
    </item>
    <item>
      <title>نوشتن اسکریپت‌های Bash که خراب نمی‌شوند</title>
      <link>https://cryo-networks.com/posts/bash-scripts-that-dont-break/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/bash-scripts-that-dont-break/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>لینوکس</category>
      <description>بیشتر اسکریپت‌های شل خوب کار می‌کنند تا وقتی که نام یک فایل فاصله داشته باشد یا دستوری وسط کار شکست بخورد. حالت سخت‌گیرانه، کوتیشن‌گذاری، فایل‌های موقت امن و trap برای پاک‌سازی را یاد بگیرید و همه را در یک اسکریپت پشتیبان‌گیری واقعی کنار هم بگذارید.</description>
      <content:encoded>&lt;p&gt;اسکریپت‌های Bash معمولاً با چند دستور شروع می‌شوند که در یک فایل چسبانده شده‌اند. روی کامپیوتر خودتان، با فایل‌های خودتان، در یک روز خوب کار می‌کنند. بعد یک شب نام فایلی فاصله دارد، دیسک پر می‌شود یا دستوری وسط کار شکست می‌خورد، و اسکریپت طوری ادامه می‌دهد که انگار هیچ اتفاقی نیفتاده؛ گاهی هم سر راه چیزهای اشتباهی را پاک می‌کند.&lt;/p&gt;
&lt;p&gt;راه‌حل‌ها کم و مکانیکی‌اند. این مقاله عادت‌هایی را مرور می‌کند که باعث می‌شوند اسکریپت‌ها &lt;strong&gt;با سروصدا و به‌شکل امن&lt;/strong&gt; شکست بخورند، و بعد همه را در یک اسکریپت پشتیبان‌گیری که واقعاً می‌توانید از آن استفاده کنید ترکیب می‌کند. فرض بر این است که با دستورهای &lt;a href=&#34;/posts/linux-command-line-essentials/&#34;&gt;دستورهای ضروری لینوکس که هر برنامه‌نویسی باید بداند&lt;/a&gt; راحت هستید.&lt;/p&gt;
&lt;h2 id=&#34;هر-اسکریپت-را-یکجور-شروع-کنید&#34;&gt;هر اسکریپت را یک‌جور شروع کنید&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;ch&#34;&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-euo&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;pipefail&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;خط اول (که به آن &lt;em&gt;shebang&lt;/em&gt; می‌گویند) مشخص می‌کند کدام برنامه فایل را اجرا کند. &lt;code&gt;/usr/bin/env bash&lt;/code&gt; برنامهٔ &lt;code&gt;bash&lt;/code&gt; را هر جا که نصب شده باشد پیدا می‌کند، که روی macOS و BSD مهم است. یک بار با &lt;code&gt;chmod +x script.sh&lt;/code&gt; فایل را اجرایی کنید و آن را با &lt;code&gt;./script.sh&lt;/code&gt; اجرا کنید.&lt;/p&gt;
&lt;p&gt;خط دوم چیزی را روشن می‌کند که معمولاً &lt;strong&gt;حالت سخت‌گیرانه&lt;/strong&gt; (strict mode) نامیده می‌شود. هر حرف جلوی یک شکستِ بی‌صدای متفاوت را می‌گیرد.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;حالت سخت‌گیرانه چه چیزهایی را می‌گیرد: set -e بعد از یک cd ناموفق متوقف می‌شود، set -u یک متغیرِ غلط‌نوشته را به خطا تبدیل می‌کند و pipefail باعث می‌شود اگر هر دستوری در یک پایپ‌لاین شکست بخورد، کل پایپ‌لاین شکست بخورد&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&#34;گزینه-set-e-با-اولین-خطا-متوقف-شو&#34;&gt;گزینهٔ set -e: با اولین خطا متوقف شو&lt;/h2&gt;
&lt;p&gt;Bash به‌طور پیش‌فرض شکست‌ها را نادیده می‌گیرد و به هر حال خط بعدی را اجرا می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/var/www/myapp-typo&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# fails: No such file or directory&lt;/span&gt;
rm&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-rf&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;./*&lt;span class=&#34;w&#34;&gt;                    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# ...and now runs in whatever directory you were in&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;با &lt;code&gt;set -e&lt;/code&gt;، اسکریپت به محض اینکه دستوری شکست بخورد (کد خروجِ غیرصفر برگرداند) خارج می‌شود. شکست‌هایی که انتظارشان را دارید، مثل &lt;code&gt;grep&lt;/code&gt;ی که چیزی پیدا نمی‌کند، را می‌توان صریحاً مدیریت کرد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;grep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-q&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;ERROR&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;app.log&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Errors found&amp;quot;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;

grep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-q&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;ERROR&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;app.log&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;No errors&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# || also counts as handling it&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;جاهایی که set -e کمکی نمی‌کند&lt;/p&gt;
&lt;p&gt;&lt;code&gt;set -e&lt;/code&gt; در شرط‌ها (&lt;code&gt;if&lt;/code&gt;، &lt;code&gt;while&lt;/code&gt;، &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;، &lt;code&gt;||&lt;/code&gt;) نادیده گرفته می‌شود و دو نقطهٔ کورِ معروف هم دارد:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;local out=$(some_command)&lt;/code&gt; هرگز شکست نمی‌خورد، چون کد خروجی که می‌گیرید مالِ &lt;code&gt;local&lt;/code&gt; است. اعلان و مقداردهی را در دو خط جدا انجام دهید: اول &lt;code&gt;local out&lt;/code&gt; و بعد &lt;code&gt;out=$(some_command)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;((count++))&lt;/code&gt; وقتی &lt;code&gt;count&lt;/code&gt; صفر بوده ۱ برمی‌گرداند، که با &lt;code&gt;set -e&lt;/code&gt; &lt;strong&gt;اسکریپت را می‌کُشد&lt;/strong&gt;. به‌جای آن از &lt;code&gt;count=$((count + 1))&lt;/code&gt; استفاده کنید.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&#34;گزینه-set-u-متغیر-تعریفنشده-ممنوع&#34;&gt;گزینهٔ set -u: متغیرِ تعریف‌نشده ممنوع&lt;/h2&gt;
&lt;p&gt;یک غلط تایپی در نام متغیر معمولاً بی‌صدا به یک رشتهٔ خالی تبدیل می‌شود:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nv&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Hello, &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$nme&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# prints &amp;quot;Hello, &amp;quot; without set -u&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;این در یک &lt;code&gt;echo&lt;/code&gt; آزاردهنده است و در &lt;code&gt;rm -rf &#34;$build_dir/&#34;*&lt;/code&gt; خطرناک. با &lt;code&gt;set -u&lt;/code&gt;، استفاده از متغیری که مقدار ندارد خطاست:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;./greet.sh: line 3: nme: unbound variable&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;برای متغیرهایی که &lt;em&gt;مجازند&lt;/em&gt; نباشند، با &lt;code&gt;${var:-default}&lt;/code&gt; مقدار پیش‌فرض بدهید، یا با &lt;code&gt;${var:?message}&lt;/code&gt; با پیامِ خودتان شکست بخورید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nv&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PORT&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;:-&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;8080&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                          &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# use $PORT if set, otherwise 8080&lt;/span&gt;
:&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;API_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:?API_KEY must be set&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# stop with this error if it&amp;#39;s missing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;گزینه-set-o-pipefail-شکستهای-داخل-پایپلاین&#34;&gt;گزینهٔ set -o pipefail: شکست‌های داخل پایپ‌لاین&lt;/h2&gt;
&lt;p&gt;کد خروجِ یک پایپ‌لاین معمولاً کد خروجِ &lt;strong&gt;آخرین&lt;/strong&gt; دستور آن است؛ پس شکست‌های قبلی در پایپ ناپدید می‌شوند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;true&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$?&lt;/span&gt;
&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-o&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;pipefail
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;true&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$?&lt;/span&gt;
&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;بدون آن، &lt;code&gt;mysqldump mydb | gzip &amp;gt; backup.sql.gz&lt;/code&gt; حتی وقتی dump شکست می‌خورد «موفق» است، چون &lt;code&gt;gzip&lt;/code&gt; با خوشحالی یک ورودیِ خالی را فشرده می‌کند. با &lt;code&gt;pipefail&lt;/code&gt;، اگر &lt;strong&gt;هر&lt;/strong&gt; دستوری در پایپ‌لاین شکست بخورد، کل پایپ‌لاین شکست می‌خورد.&lt;/p&gt;
&lt;h2 id=&#34;متغیرها-را-داخل-کوتیشن-بگذارید&#34;&gt;متغیرها را داخل کوتیشن بگذارید&lt;/h2&gt;
&lt;p&gt;این بزرگ‌ترین منبعِ باگ‌های شل است. یک &lt;code&gt;$var&lt;/code&gt; بدون کوتیشن &lt;strong&gt;روی فاصله‌ها شکسته می‌شود&lt;/strong&gt; و بعد &lt;strong&gt;به‌عنوان الگوی wildcard گسترش پیدا می‌کند&lt;/strong&gt;:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nv&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;my report.txt&amp;quot;&lt;/span&gt;
rm&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$file&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# rm: cannot remove &amp;#39;my&amp;#39;: No such file or directory&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;                  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# rm: cannot remove &amp;#39;report.txt&amp;#39;: No such file or directory&lt;/span&gt;
rm&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$file&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# removes &amp;quot;my report.txt&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;و اگر متغیری &lt;code&gt;*&lt;/code&gt; داشته باشد، گسترشِ بدون کوتیشن آن را به فهرستی از فایل‌های پوشهٔ فعلی تبدیل می‌کند. قانون ساده است: &lt;strong&gt;همیشه دور متغیرها و جایگزینی‌های دستور (command substitution) کوتیشن دوتایی بگذارید&lt;/strong&gt;: &lt;code&gt;&#34;$file&#34;&lt;/code&gt;، &lt;code&gt;&#34;$(date +%F)&#34;&lt;/code&gt;، &lt;code&gt;&#34;${files[@]}&#34;&lt;/code&gt;. استثناهای نادر عمدی‌اند و یک کامنت توضیحی لازم دارند.&lt;/p&gt;
&lt;p&gt;برای فرستادنِ همهٔ آرگومان‌های اسکریپت به یک دستور دیگر، از &lt;code&gt;&#34;$@&#34;&lt;/code&gt; استفاده کنید. هر آرگومان را دست‌نخورده نگه می‌دارد، حتی وقتی فاصله داشته باشد؛ &lt;code&gt;$*&lt;/code&gt; و &lt;code&gt;$@&lt;/code&gt; بدون کوتیشن این کار را نمی‌کنند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;c1&#34;&gt;# called as: ./wrapper.sh &amp;quot;a b&amp;quot; c&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;arg&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$@&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;[&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;]&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# [a b] [c]&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;arg&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;[&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;]&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# [a] [b] [c]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;برای شرط‌ها از [[ ]] استفاده کنید&lt;/p&gt;
&lt;p&gt;در Bash، &lt;code&gt;[[ -f &#34;$file&#34; ]]&lt;/code&gt; را به &lt;code&gt;[ -f &#34;$file&#34; ]&lt;/code&gt; ترجیح دهید. کلمه‌ها را نمی‌شکند، پس یک کوتیشنِ جاافتاده خرابش نمی‌کند، و از &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;، &lt;code&gt;||&lt;/code&gt; و تطبیق الگو مثل &lt;code&gt;[[ $name == *.txt ]]&lt;/code&gt; پشتیبانی می‌کند.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;خواندن-درست-فایل-خطبهخط&#34;&gt;خواندنِ درستِ فایل، خط‌به‌خط&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;for line in $(cat file)&lt;/code&gt; روی &lt;strong&gt;کلمه‌ها&lt;/strong&gt; حلقه می‌زند، نه خط‌ها، و سر راه wildcardها را هم گسترش می‌دهد. روش درست این است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;IFS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;read&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-r&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;line&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Processing: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$line&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;lt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;hosts.txt&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;IFS=&lt;/code&gt; فاصله‌های ابتدا و انتهای خط را نگه می‌دارد و &lt;code&gt;-r&lt;/code&gt; جلوی تفسیر بک‌اسلش‌ها به‌عنوان کاراکتر escape را می‌گیرد.&lt;/p&gt;
&lt;h2 id=&#34;پاکسازی-با-trap&#34;&gt;پاک‌سازی با trap&lt;/h2&gt;
&lt;p&gt;اسکریپت‌ها اغلب فایل‌های موقت می‌سازند. &lt;code&gt;mktemp&lt;/code&gt; فایلی با نامی یکتا و غیرقابل حدس می‌سازد (هرگز &lt;code&gt;/tmp/myscript.tmp&lt;/code&gt; را ثابت در کد ننویسید)، و &lt;code&gt;trap ... EXIT&lt;/code&gt; تضمین می‌کند که آن فایل هر طور اسکریپت تمام شود پاک شود: به‌طور عادی، به‌خاطر خطا با &lt;code&gt;set -e&lt;/code&gt;، یا وقتی &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;C&lt;/kbd&gt; را می‌زنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nv&#34;&gt;tmpdir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;mktemp&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-d&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;trap&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;rm -rf &amp;quot;$tmpdir&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;EXIT

curl&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-fsSL&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;https://example.com/data.csv&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-o&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$tmpdir&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/data.csv&amp;quot;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# ...work with the file; no matter what happens, $tmpdir is deleted at the end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;به کوتیشن تکی دقت کنید: &lt;code&gt;$tmpdir&lt;/code&gt; وقتی trap &lt;em&gt;اجرا می‌شود&lt;/em&gt; گسترش پیدا می‌کند، نه وقتی تعریف می‌شود. فقط &lt;code&gt;kill -9&lt;/code&gt; (یعنی SIGKILL) از trap رد می‌شود، چون هیچ چیزی نمی‌تواند آن سیگنال را بگیرد.&lt;/p&gt;
&lt;h2 id=&#34;تابعها-آرگومانها-و-خطاها&#34;&gt;تابع‌ها، آرگومان‌ها و خطاها&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;die&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Error: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$*&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# error messages go to stderr&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;

require_dir&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;local&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;dir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# local: don&amp;#39;t leak into the rest of the script&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-d&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$dir&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;die&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$dir&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#39; is not a directory&amp;quot;&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;داخل یک تابع، &lt;code&gt;$1&lt;/code&gt;، &lt;code&gt;$2&lt;/code&gt;… و &lt;code&gt;&#34;$@&#34;&lt;/code&gt; آرگومان‌های خودِ تابع هستند. برای هر متغیری که تابع می‌سازد از &lt;code&gt;local&lt;/code&gt; استفاده کنید، خطاها را در خروجیِ خطای استاندارد (&lt;code&gt;&amp;gt;&amp;amp;2&lt;/code&gt;) چاپ کنید تا با خروجیِ واقعی قاطی نشوند، و با یک کد غیرصفر خارج شوید تا فراخواننده (یک آدم، &lt;code&gt;cron&lt;/code&gt; یا CI) بفهمد مشکلی پیش آمده.&lt;/p&gt;
&lt;h2 id=&#34;یک-مثال-کامل-اسکریپت-پشتیبانگیری&#34;&gt;یک مثال کامل: اسکریپت پشتیبان‌گیری&lt;/h2&gt;
&lt;p&gt;این اسکریپتی است که از یک پوشه آرشیو می‌سازد، فقط چند آرشیوِ آخر را نگه می‌دارد و همهٔ نکته‌های بالا را عملاً به کار می‌گیرد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;ch&#34;&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# backup.sh: archive a directory and keep only the newest few archives.&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-euo&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;pipefail

usage&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Usage: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$0&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; SOURCE_DIR DEST_DIR [KEEP]&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$#&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-ge&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;usage
&lt;span class=&#34;nv&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$1&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$2&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;keep&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;:-&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-d&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$src&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Error: &amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$src&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#39; is not a directory&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
mkdir&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$dest&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Write to a temporary file first, so a failed run never leaves a half-written archive behind&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;tmpfile&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;mktemp&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$dest&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/.backup.XXXXXX&amp;quot;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;trap&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;rm -f &amp;quot;$tmpfile&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;EXIT

&lt;span class=&#34;nv&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;basename&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$src&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;date&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;+%Y%m%d-%H%M%S&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.tar.gz&amp;quot;&lt;/span&gt;
tar&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-czf&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$tmpfile&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-C&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;dirname&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$src&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;basename&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$src&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;
mv&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$tmpfile&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$dest&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$name&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Created &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$dest&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$name&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# The timestamp in the name sorts alphabetically, so the glob lists the oldest first&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;archives&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$dest&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;basename&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$src&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;-*.tar.gz&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;excess&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$((&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${#&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;archives&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[@]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;keep&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;i&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;lt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;excess&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;i++&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;rm&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;archives&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[i]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Removed &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;archives&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[i]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;./backup.sh&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;my site&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;backups&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;
Created&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;backups/my&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;site-20261029-081312.tar.gz
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;./backup.sh&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;my site&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;backups&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;
Created&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;backups/my&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;site-20261029-081313.tar.gz
$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;./backup.sh&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;my site&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;backups&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;
Created&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;backups/my&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;site-20261029-081314.tar.gz
Removed&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;backups/my&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;site-20261029-081312.tar.gz&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;چند جزئیات که ارزش دیدن دارند:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;پوشهٔ مبدئی را که نامش فاصله دارد درست مدیریت می‌کند، چون همهٔ متغیرها داخل کوتیشن‌اند.&lt;/li&gt;
&lt;li&gt;آرشیو با یک نامِ موقت نوشته می‌شود و در پایان &lt;strong&gt;تغییر نام&lt;/strong&gt; داده می‌شود. تغییر نام داخل یک پوشه اتمی است؛ پس پوشهٔ پشتیبان‌ها هرگز یک آرشیوِ نیمه‌کاره ندارد، حتی اگر &lt;code&gt;tar&lt;/code&gt; شکست بخورد یا دیسک پر شود. (&lt;code&gt;mktemp&lt;/code&gt; همچنین فایل را فقط برای خودتان خواندنی می‌کند، که برای پشتیبان مناسب است.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rm --&lt;/code&gt; پایانِ گزینه‌ها را مشخص می‌کند؛ پس نام فایلی که با &lt;code&gt;-&lt;/code&gt; شروع می‌شود با یک گزینه اشتباه گرفته نمی‌شود.&lt;/li&gt;
&lt;li&gt;استفادهٔ غلط با کد ۲ و خطاهای واقعی با کد ۱ خارج می‌شوند؛ پس یک کار &lt;code&gt;cron&lt;/code&gt; یا پایپ‌لاین CI می‌تواند آن‌ها را از هم تشخیص دهد.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;بگذارید-shellcheck-اسکریپتهایتان-را-بازبینی-کند&#34;&gt;بگذارید ShellCheck اسکریپت‌هایتان را بازبینی کند&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://www.shellcheck.net/&#34;&gt;ShellCheck&lt;/a&gt; یک linter برای اسکریپت‌های شل است. کوتیشن‌های جاافتاده، تلهٔ &lt;code&gt;local&lt;/code&gt;، تفاوت &lt;code&gt;$*&lt;/code&gt; و &lt;code&gt;&#34;$@&#34;&lt;/code&gt; و ده‌ها اشتباه دیگر را می‌گیرد و برای هر کدام توضیح می‌دهد. با &lt;code&gt;sudo apt install shellcheck&lt;/code&gt; (یا &lt;code&gt;brew install shellcheck&lt;/code&gt;) نصبش کنید، &lt;code&gt;shellcheck backup.sh&lt;/code&gt; را اجرا کنید و آن را به ویرایشگر یا CIتان اضافه کنید. سریع‌ترین راه برای جا انداختنِ همهٔ این عادت‌هاست.&lt;/p&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;با &lt;code&gt;#!/usr/bin/env bash&lt;/code&gt; و &lt;strong&gt;&lt;code&gt;set -euo pipefail&lt;/code&gt;&lt;/strong&gt; شروع کنید و بدانید &lt;code&gt;set -e&lt;/code&gt; به کجاها نمی‌رسد.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;هر گسترشی را داخل کوتیشن بگذارید&lt;/strong&gt;: &lt;code&gt;&#34;$var&#34;&lt;/code&gt;، &lt;code&gt;&#34;$(cmd)&#34;&lt;/code&gt;، &lt;code&gt;&#34;$@&#34;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;برای مقدارهای اختیاری و الزامی از &lt;code&gt;${var:-default}&lt;/code&gt; و &lt;code&gt;${var:?message}&lt;/code&gt; استفاده کنید.&lt;/li&gt;
&lt;li&gt;فایل‌های موقت را با &lt;strong&gt;&lt;code&gt;mktemp&lt;/code&gt;&lt;/strong&gt; بسازید و با &lt;strong&gt;&lt;code&gt;trap &#39;...&#39; EXIT&lt;/code&gt;&lt;/strong&gt; پاکشان کنید.&lt;/li&gt;
&lt;li&gt;خطاها را به &lt;code&gt;&amp;gt;&amp;amp;2&lt;/code&gt; بفرستید، با کدهای خروجِ معنادار خارج شوید و &lt;strong&gt;ShellCheck&lt;/strong&gt; را اجرا کنید.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
    </item>
    <item>
      <title>ریبیس تعاملی: کامیت‌هایتان را قبل از اشتراک‌گذاری مرتب کنید</title>
      <link>https://cryo-networks.com/posts/git-interactive-rebase/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/git-interactive-rebase/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>گیت</category>
      <description>با git rebase -i یک ردِ شلوغ از کامیت‌های نیمه‌کاره را به تاریخچه‌ای تمیز و قابل بازبینی تبدیل کنید. کامیت‌ها را ادغام، بازنویسی، جابه‌جا، تقسیم و حذف کنید و بگذارید کامیت‌های fixup مرتب‌سازی را برایتان انجام دهند.</description>
      <content:encoded>&lt;p&gt;کارِ واقعی شلوغ است. یک فرمِ نیمه‌کاره را کامیت می‌کنید، بعد «WIP»، بعد «fix typo»، بعد یک print برای دیباگ که یادتان رفته پاکش کنید. تا وقتی مشغول کارید اشکالی ندارد، اما این تاریخچهٔ خوبی برای تحویل به بازبین نیست، و برای پیدا کردنش شش ماه بعد در &lt;code&gt;git log&lt;/code&gt; یا &lt;code&gt;git blame&lt;/code&gt; از آن هم بدتر است.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ریبیس تعاملی&lt;/strong&gt; (interactive rebase) به شما اجازه می‌دهد برنچ خودتان را قبل از اشتراک‌گذاری بازنویسی کنید: کامیت‌ها را با هم ادغام کنید، پیامشان را از نو بنویسید، ترتیبشان را عوض کنید، آن‌ها را تقسیم یا حذف کنید. وقتی با برنچ‌ها راحت شدید، این یکی از مفیدترین مهارت‌هایی است که در گیت می‌توانید یاد بگیرید. اگر هنوز راحت نیستید، اول &lt;a href=&#34;/posts/git-branching-workflow/&#34;&gt;روش کاری عملی با برنچ‌های گیت برای مبتدی‌ها&lt;/a&gt; را بخوانید.&lt;/p&gt;
&lt;h2 id=&#34;برنچ-شلوغ&#34;&gt;برنچِ شلوغ&lt;/h2&gt;
&lt;p&gt;این یک برنچ فیچر با پنج کامیت روی &lt;code&gt;main&lt;/code&gt; است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;log&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--oneline&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main..
746aec7&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;debug&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;print
451c410&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;fix&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;typo
63d1135&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;password&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;validation
0ce6ff7&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;WIP
4430f61&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;login&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;form&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;main..&lt;/code&gt; یعنی «کامیت‌هایی از این برنچ که در &lt;code&gt;main&lt;/code&gt; نیستند». چیزی که می‌خواهیم به اشتراک بگذاریم فقط دو کامیت است: &lt;em&gt;Add login form&lt;/em&gt; (به‌همراه WIP و رفع غلط تایپی که هر دو روی همان فرم بودند) و &lt;em&gt;Add password validation&lt;/em&gt;، بدون print دیباگ.&lt;/p&gt;
&lt;h2 id=&#34;شروع-ریبیس-تعاملی&#34;&gt;شروع ریبیس تعاملی&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;rebase&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-i&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;گیت ویرایشگرتان را با یک &lt;strong&gt;فهرست کار&lt;/strong&gt; (todo list) باز می‌کند؛ برای هر کامیت یک خط:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;pick 4430f61 Add login form
pick 0ce6ff7 WIP
pick 63d1135 Add password validation
pick 451c410 fix typo
pick 746aec7 debug print

# Rebase 1c893f9..746aec7 onto 1c893f9 (5 commands)
#
# Commands:
# p, pick &amp;lt;commit&amp;gt; = use commit
# r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message
# e, edit &amp;lt;commit&amp;gt; = use commit, but stop for amending
# s, squash &amp;lt;commit&amp;gt; = use commit, but meld into previous commit
# f, fixup [-C | -c] &amp;lt;commit&amp;gt; = like &amp;quot;squash&amp;quot; but keep only the previous
#                    commit&amp;#39;s log message, unless -C is used, ...
# d, drop &amp;lt;commit&amp;gt; = remove commit
# ...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;فهرست کار نسبت به git log برعکس است&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git log&lt;/code&gt; جدیدترین کامیت را اول نشان می‌دهد. فهرست کار &lt;strong&gt;قدیمی‌ترین را اول&lt;/strong&gt; نشان می‌دهد، چون گیت کامیت‌ها را به همین ترتیب دوباره اعمال می‌کند. آن را مثل یک اسکریپت از بالا به پایین بخوانید.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;گیت از &lt;code&gt;main&lt;/code&gt; شروع می‌کند و خط‌ها را یکی‌یکی اجرا می‌کند. کلمهٔ اول هر خط را عوض کنید تا بلایی که سر آن کامیت می‌آید عوض شود:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;دستور&lt;/th&gt;
&lt;th&gt;چه کاری می‌کند&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pick&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;کامیت را همان‌طور که هست نگه می‌دارد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reword&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;تغییرات را نگه می‌دارد، اما می‌ایستد تا پیام را ویرایش کنید&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;edit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;کامیت را اعمال می‌کند و بعد مکث می‌کند تا آن را تغییر دهید (amend، تقسیم و…)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;squash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;در کامیتِ بالایی ادغام می‌شود و هر دو پیام را با هم ترکیب می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fixup&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;در کامیتِ بالایی ادغام می‌شود و پیامِ این کامیت را دور می‌ریزد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;drop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;کامیت را حذف می‌کند (پاک کردنِ خط هم همین کار را می‌کند)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;exec&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;در این نقطه یک دستور شل اجرا می‌کند و اگر شکست بخورد می‌ایستد&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;ادغام-جابهجایی-و-حذف&#34;&gt;ادغام، جابه‌جایی و حذف&lt;/h2&gt;
&lt;p&gt;فهرست کار را این‌طور ویرایش کنید، بعد ذخیره کنید و ویرایشگر را ببندید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;pick 4430f61 Add login form
fixup 0ce6ff7 WIP
fixup 451c410 fix typo
pick 63d1135 Add password validation
drop 746aec7 debug print&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;سه چیز را عوض کردیم: دو کامیتِ کوچک به &lt;code&gt;fixup&lt;/code&gt; &lt;em&gt;Add login form&lt;/em&gt; تبدیل شدند، &lt;em&gt;fix typo&lt;/em&gt; را &lt;strong&gt;بالا بردیم&lt;/strong&gt; تا درست زیرِ کامیتی قرار بگیرد که اصلاحش می‌کند، و print دیباگ حذف شد.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;rebase&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-i&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main
Successfully&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;rebased&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;and&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;updated&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;refs/heads/login-form.

$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;log&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--oneline&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main..
486c6b2&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;password&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;validation
24c6dfe&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;login&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;form&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;فهرست کار از بالا به پایین خوانده می‌شود: دو fixup در Add login form ذوب می‌شوند، Add password validation می‌ماند و print دیباگ حذف می‌شود؛ نتیجه دو کامیتِ تمیز است&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;دقت کنید که هش‌ها عوض شدند، حتی برای &lt;em&gt;Add password validation&lt;/em&gt; که به محتوایش دست نزدیم. ریبیس هرگز کامیت‌ها را ویرایش نمی‌کند: کامیت‌های &lt;strong&gt;جدیدی&lt;/strong&gt; با همان تغییرات می‌سازد. این نکته جلوتر، موقع push، مهم می‌شود.&lt;/p&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;squash یا fixup؟&lt;/p&gt;
&lt;p&gt;وقتی پیامِ کامیت دوم چیزی دارد که ارزش نگه‌داشتن دارد از &lt;code&gt;squash&lt;/code&gt; استفاده کنید: گیت ویرایشگر را با هر دو پیام باز می‌کند تا آن‌ها را با هم ترکیب کنید. برای کامیت‌های «اوه، یادم رفت» که پیامشان را به هر حال پاک می‌کردید، &lt;code&gt;fixup&lt;/code&gt; را به کار ببرید.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;کامیتهای-fixup-در-حین-کار-مرتب-کنید&#34;&gt;کامیت‌های fixup: در حین کار مرتب کنید&lt;/h2&gt;
&lt;p&gt;جابه‌جا کردنِ دستیِ خط‌ها خسته‌کننده می‌شود. اگر از قبل می‌دانید یک تغییر مال کدام کامیت است، موقع کامیت کردن به گیت بگویید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;c1&#34;&gt;# Spotted a bug in &amp;quot;Add password validation&amp;quot;? Fix it, then:&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;commit&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-a&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--fixup&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;486c6b2&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;گیت کامیتی به نام &lt;code&gt;fixup! Add password validation&lt;/code&gt; می‌سازد. بعداً &lt;code&gt;--autosquash&lt;/code&gt; همهٔ این کامیت‌ها را زیرِ کامیتِ هدفشان می‌برد و برایتان &lt;code&gt;fixup&lt;/code&gt; علامت می‌زند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;rebase&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-i&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--autosquash&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;pick 24c6dfe Add login form
pick 486c6b2 Add password validation
fixup 4eb2adb fixup! Add password validation&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;فقط ذخیره کنید و ببندید. برای اینکه این رفتار پیش‌فرض شود، &lt;code&gt;git config --global rebase.autoSquash true&lt;/code&gt; را اجرا کنید.&lt;/p&gt;
&lt;h2 id=&#34;تقسیم-یک-کامیت-با-edit&#34;&gt;تقسیم یک کامیت با edit&lt;/h2&gt;
&lt;p&gt;گاهی یک کامیت دو کارِ بی‌ربط انجام می‌دهد. آن را &lt;code&gt;edit&lt;/code&gt; علامت بزنید تا گیت درست بعد از اعمالش مکث کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;edit 9a1c2d3 Add login form and fix footer links
pick 3f7e8b1 Add password validation&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;reset&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;HEAD^&lt;span class=&#34;w&#34;&gt;                 &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# undo the commit, keep its changes as unstaged edits&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;login.html
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;commit&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-m&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Add login form&amp;quot;&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;footer.html
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;commit&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-m&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Fix footer links&amp;quot;&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;rebase&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--continue&lt;span class=&#34;w&#34;&gt;           &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# carry on with the rest of the todo list&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;وقتی هر دو تغییر در یک فایل هستند، &lt;code&gt;git add -p&lt;/code&gt; اینجا به کار می‌آید: دربارهٔ هر تکه از تغییرات جداگانه از شما می‌پرسد.&lt;/p&gt;
&lt;h2 id=&#34;وقتی-تداخل-پیش-میآید&#34;&gt;وقتی تداخل پیش می‌آید&lt;/h2&gt;
&lt;p&gt;جابه‌جا یا حذف کردن کامیت‌ها ممکن است تداخل (conflict) ایجاد کند، دقیقاً مثل merge. گیت می‌ایستد و می‌گوید کدام فایل‌ها تداخل دارند. سه راه دارید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;c1&#34;&gt;# fix the files, then mark them as resolved and continue&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;login.html
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;rebase&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--continue

git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;rebase&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--skip&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# drop the commit that conflicts and move on&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;rebase&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--abort&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# give up: put the branch back exactly as it was&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;--abort&lt;/code&gt; تور ایمنی شماست. تا وقتی ریبیس تمام نشده، هیچ چیزی واقعاً تغییر نکرده است.&lt;/p&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;تست‌ها را روی تک‌تکِ کامیت‌ها اجرا کنید&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git rebase -i main --exec &#34;npm test&#34;&lt;/code&gt; (یا &lt;code&gt;-x&lt;/code&gt;) بعد از هر کامیت یک خط &lt;code&gt;exec&lt;/code&gt; اضافه می‌کند. اگر تست‌ها هر جایی شکست بخورند، ریبیس روی همان کامیتی می‌ایستد که آن‌ها را خراب کرده. این یک بررسی نهاییِ عالی است که هر کامیت به‌تنهایی کار می‌کند؛ همان چیزی که بعدها &lt;code&gt;git bisect&lt;/code&gt; را مفید می‌کند.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;ریبیس-بدون-جابهجا-کردن-برنچ&#34;&gt;ریبیس بدون جابه‌جا کردنِ برنچ&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;git rebase -i main&lt;/code&gt; برنچ شما را روی &lt;strong&gt;آخرین&lt;/strong&gt; نسخهٔ &lt;code&gt;main&lt;/code&gt; هم می‌برد. معمولاً همین را می‌خواهید، اما اگر &lt;code&gt;main&lt;/code&gt; خیلی جلو رفته باشد، به تداخل‌هایی می‌خورید که هیچ ربطی به مرتب‌سازیِ شما ندارند. برای مرتب کردن کامیت‌ها سرِ جایشان، با همان نقطهٔ شروع:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;rebase&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-i&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--keep-base&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;نقطهٔ شروع را مستقیم هم می‌توانید بدهید: &lt;code&gt;git rebase -i HEAD~3&lt;/code&gt; اجازه می‌دهد سه کامیت آخر را ویرایش کنید.&lt;/p&gt;
&lt;h2 id=&#34;push-کردن-یک-برنچ-بازنویسیشده&#34;&gt;push کردنِ یک برنچِ بازنویسی‌شده&lt;/h2&gt;
&lt;p&gt;چون کامیت‌ها جدیدند، برنچی که قبل از ریبیس push کرده بودید دیگر با ریموت جور نیست و یک &lt;code&gt;git push&lt;/code&gt; معمولی رد می‌شود. از این استفاده کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;push&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--force-with-lease&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;برخلاف &lt;code&gt;--force&lt;/code&gt;، اگر از آخرین fetch شما کس دیگری روی برنچِ ریموت push کرده باشد، &lt;code&gt;--force-with-lease&lt;/code&gt; از بازنویسی آن خودداری می‌کند؛ پس نمی‌توانید تصادفاً کارِ هم‌تیمی‌تان را پاک کنید.&lt;/p&gt;
&lt;div class=&#34;admonition danger&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;قانون طلایی ریبیس&lt;/p&gt;
&lt;p&gt;فقط کامیت‌هایی را بازنویسی کنید که هیچ‌کس روی آن‌ها کار نساخته است. مرتب کردنِ برنچ فیچرِ خودتان قبل از pull request (یا در حین آن) مشکلی ندارد. ریبیس کردنِ &lt;code&gt;main&lt;/code&gt;، یا برنچی که هم‌تیمی‌هایتان pull کرده‌اند، برایشان نسخه‌هایی از کامیت‌های قدیمی و یک merge دردناک باقی می‌گذارد.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;برگرداندن-یک-ریبیس&#34;&gt;برگرداندن یک ریبیس&lt;/h2&gt;
&lt;p&gt;ریبیس را تمام کرده‌اید و پشیمانید؟ گیت جای قبلیِ برنچ شما را در &lt;code&gt;ORIG_HEAD&lt;/code&gt; نگه می‌دارد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;reset&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--hard&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;ORIG_HEAD&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;این فقط درست بعد از ریبیس کار می‌کند، چون دستورهای دیگر هم &lt;code&gt;ORIG_HEAD&lt;/code&gt; را به‌روز می‌کنند. برای عقب‌تر، reflog هر جایی را که برنچتان بوده به خاطر دارد (&lt;code&gt;git reflog&lt;/code&gt;). &lt;a href=&#34;/posts/git-internals-objects-refs/&#34;&gt;گیت واقعاً چطور کار می‌کند&lt;/a&gt; توضیح می‌دهد چرا کامیت‌های قدیمی هنوز آنجا هستند.&lt;/p&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git rebase -i main&lt;/code&gt; یک &lt;strong&gt;فهرست کار&lt;/strong&gt; از کامیت‌های برنچتان باز می‌کند، با &lt;strong&gt;قدیمی‌ترین در ابتدا&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pick&lt;/code&gt; را به &lt;code&gt;reword&lt;/code&gt;، &lt;code&gt;edit&lt;/code&gt;، &lt;code&gt;squash&lt;/code&gt;، &lt;code&gt;fixup&lt;/code&gt; یا &lt;code&gt;drop&lt;/code&gt; تغییر دهید و برای عوض کردن ترتیب کامیت‌ها، خط‌ها را جابه‌جا کنید.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit --fixup=&amp;lt;commit&amp;gt;&lt;/code&gt; به‌همراه &lt;code&gt;--autosquash&lt;/code&gt; مرتب‌سازی را تقریباً خودکار می‌کند.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--abort&lt;/code&gt; یک ریبیسِ در جریان را متوقف می‌کند؛ &lt;code&gt;ORIG_HEAD&lt;/code&gt; و reflog یک ریبیسِ تمام‌شده را برمی‌گردانند.&lt;/li&gt;
&lt;li&gt;ریبیس کامیت‌های جدید می‌سازد، پس با &lt;code&gt;--force-with-lease&lt;/code&gt; push کنید، و &lt;strong&gt;هرگز کامیت‌هایی را که دیگران روی آن‌ها کار ساخته‌اند ریبیس نکنید&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
    </item>
    <item>
      <title>دیسکریپتورها در پایتون: پروتکلی که پشت property و متدهاست</title>
      <link>https://cryo-networks.com/posts/python-descriptors-explained/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/python-descriptors-explained/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>پایتون</category>
      <description>property، متدهای bound، cached_property و __slots__ همه روی یک پروتکل کوچک کار می‌کنند. یاد بگیرید دیسکریپتورها چطور کار می‌کنند، ترتیب دقیق جست‌وجوی attributeها چیست و چطور دیسکریپتور خودتان را بنویسید.</description>
      <content:encoded>&lt;p&gt;تا حالا فکر کرده‌اید &lt;code&gt;@property&lt;/code&gt; چطور یک متد را به چیزی تبدیل می‌کند که شبیه یک attributeِ ساده است؟ یا وقتی &lt;code&gt;obj.method()&lt;/code&gt; را صدا می‌زنید، &lt;code&gt;self&lt;/code&gt; دقیقاً از کجا می‌آید؟ یا فیلدهای مدل در Django و ستون‌های SQLAlchemy از کجا می‌فهمند متعلق به کدام شیء هستند؟&lt;/p&gt;
&lt;p&gt;همهٔ این‌ها روی یک سازوکار کوچک بنا شده‌اند: &lt;strong&gt;پروتکل دیسکریپتور&lt;/strong&gt; (descriptor protocol). این یکی از معدود بخش‌های واقعاً «جادویی» پایتون است و وقتی آن را بفهمید، هم می‌توانید سازوکار درونی زبان را بخوانید و هم منطق attributeها را تمیزتر و قابل‌استفادهٔ مجدد بنویسید.&lt;/p&gt;
&lt;p&gt;اگر دکوریتورها هنوز برایتان تازه‌اند، اول &lt;a href=&#34;/posts/python-decorators-explained/&#34;&gt;دکوریتورها در پایتون، قدم‌به‌قدم&lt;/a&gt; را بخوانید؛ در ادامه از آن‌ها استفاده می‌کنیم.&lt;/p&gt;
&lt;h2 id=&#34;دیسکریپتور-چیست&#34;&gt;دیسکریپتور چیست؟&lt;/h2&gt;
&lt;p&gt;دیسکریپتور هر شیئی است که کلاسش دست‌کم یکی از این متدها را تعریف کرده باشد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;fm&#34;&gt;__get__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;objtype&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# called when the attribute is read&lt;/span&gt;
&lt;span class=&#34;fm&#34;&gt;__set__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# called when it is assigned&lt;/span&gt;
&lt;span class=&#34;fm&#34;&gt;__delete__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;              &lt;span class=&#34;c1&#34;&gt;# called on `del obj.attr`&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;نکتهٔ مهم: این فقط وقتی کار می‌کند که دیسکریپتور به‌عنوان &lt;strong&gt;attributeِ کلاس&lt;/strong&gt; ذخیره شده باشد. وقتی پایتون دنبال &lt;code&gt;obj.attr&lt;/code&gt; می‌گردد و روی کلاس به یک دیسکریپتور می‌رسد، به‌جای برگرداندن خودِ دیسکریپتور، متد آن را صدا می‌زند.&lt;/p&gt;
&lt;h2 id=&#34;اولین-دیسکریپتور-شما-یک-attribute-اعتبارسنجیشده&#34;&gt;اولین دیسکریپتور شما: یک attributeِ اعتبارسنجی‌شده&lt;/h2&gt;
&lt;p&gt;فرض کنید هر &lt;code&gt;Product&lt;/code&gt; باید &lt;code&gt;price&lt;/code&gt; و &lt;code&gt;quantity&lt;/code&gt; مثبت داشته باشد. با property باید همان getter و setter را دو بار بنویسید. با دیسکریپتور، قانون را یک بار می‌نویسید و دوباره از آن استفاده می‌کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Positive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;&amp;quot;&amp;quot;&amp;quot;A number that must stay above zero.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;__set_name__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;owner&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;public_name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;private_name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;_&amp;quot;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__get__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;objtype&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# accessed on the class: Product.price&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;private_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__set__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;public_name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; must be positive, got &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;!r}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;nb&#34;&gt;setattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;private_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Product&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;price&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Positive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;quantity&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Positive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__init__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;price&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;quantity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;price&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;price&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# goes through Positive.__set__&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;quantity&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;quantity&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Product&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Keyboard&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;49.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;price&lt;/span&gt;
&lt;span class=&#34;mf&#34;&gt;49.0&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;vars&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Keyboard&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;_price&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;49.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;_quantity&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;quantity&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;quantity&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;must&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;be&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;positive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;got&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;سه جزئیات ارزش دقت دارد:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;__set_name__&lt;/code&gt;&lt;/strong&gt; (از پایتون ۳٫۶ به بعد) فقط یک بار و هنگام ساخته شدن کلاس صدا زده می‌شود و نام attributeی را که دیسکریپتور به آن نسبت داده شده می‌گیرد. همین است که یک کلاس &lt;code&gt;Positive&lt;/code&gt; می‌فهمد از &lt;code&gt;price&lt;/code&gt; محافظت می‌کند یا از &lt;code&gt;quantity&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;obj is None&lt;/code&gt;&lt;/strong&gt; یعنی attribute از روی خودِ کلاس خوانده شده (&lt;code&gt;Product.price&lt;/code&gt;)، نه از یک نمونه. قرارداد این است که در این حالت خودِ دیسکریپتور برگردانده شود؛ این کار باعث می‌شود ابزارهایی مثل &lt;code&gt;help()&lt;/code&gt; درست کار کنند.&lt;/li&gt;
&lt;li&gt;مقدارهای واقعی &lt;strong&gt;روی نمونه&lt;/strong&gt; و با نام‌های &lt;code&gt;_price&lt;/code&gt; و &lt;code&gt;_quantity&lt;/code&gt; ذخیره می‌شوند. دیسکریپتور فقط تنظیمات را نگه می‌دارد.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;ترتیب-جستوجوی-attributeها&#34;&gt;ترتیب جست‌وجوی attributeها&lt;/h2&gt;
&lt;p&gt;برای استفادهٔ مطمئن از دیسکریپتورها باید قوانین دقیقی را بدانید که &lt;code&gt;object.__getattribute__&lt;/code&gt; برای &lt;code&gt;obj.attr&lt;/code&gt; دنبال می‌کند. دیسکریپتورها دو نوع‌اند:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;دیسکریپتور داده&lt;/strong&gt; (data descriptor) متد &lt;code&gt;__set__&lt;/code&gt; یا &lt;code&gt;__delete__&lt;/code&gt; را تعریف می‌کند (&lt;code&gt;Positive&lt;/code&gt; و &lt;code&gt;property&lt;/code&gt; دیسکریپتور داده‌اند).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;دیسکریپتور غیرداده&lt;/strong&gt; (non-data descriptor) فقط &lt;code&gt;__get__&lt;/code&gt; را تعریف می‌کند (توابع معمولی دیسکریپتور غیرداده‌اند).&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;پایتون اول دیسکریپتور داده روی کلاس را بررسی می‌کند، بعد دیکشنری نمونه را، بعد دیسکریپتورهای غیرداده و attributeهای کلاس را، و در آخر __getattr__ را&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;این تفاوت مهم است، چون &lt;strong&gt;دیکشنری نمونه بین این دو قرار می‌گیرد&lt;/strong&gt;. می‌توانید خودتان ثابتش کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;DataDesc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__get__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;objtype&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;data descriptor&amp;quot;&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__set__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;AttributeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;read-only&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;NonDataDesc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__get__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;objtype&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;non-data descriptor&amp;quot;&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Demo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DataDesc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NonDataDesc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;


&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Demo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__dict__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;instance dict&amp;quot;&lt;/span&gt;     &lt;span class=&#34;c1&#34;&gt;# bypass __set__ and write directly&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__dict__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;b&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;instance dict&amp;quot;&lt;/span&gt;

&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# data descriptor   ← beats the instance dict&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# instance dict     ← beats the non-data descriptor&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;همین یک قانون بخش بزرگی از رفتار پایتون را توضیح می‌دهد؛ در بخش‌های بعد می‌بینید چطور.&lt;/p&gt;
&lt;h2 id=&#34;متدها-دیسکریپتور-هستند&#34;&gt;متدها دیسکریپتور هستند&lt;/h2&gt;
&lt;p&gt;توابع یک متد &lt;code&gt;__get__&lt;/code&gt; دارند. وقتی یک تابع را از طریق یک نمونه می‌خوانید، &lt;code&gt;__get__&lt;/code&gt; یک &lt;strong&gt;متد bound&lt;/strong&gt; برمی‌گرداند؛ شیء کوچکی که هم تابع و هم نمونه را به خاطر دارد. &lt;code&gt;self&lt;/code&gt; از همین‌جا می‌آید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Greeter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;     &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;hello&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;         &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;hi&amp;quot;&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Greeter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Greeter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__dict__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;# the raw function, no descriptor magic&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Greeter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hello&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;at&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x7fc890f70160&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;__get__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Greeter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;            &lt;span class=&#34;c1&#34;&gt;# exactly what g.hello does&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bound&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;method&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Greeter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hello&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;__main__&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Greeter&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;object&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;at&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x7fc890f63760&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hello&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;__get__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Greeter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;چون توابع دیسکریپتور &lt;em&gt;غیرداده&lt;/em&gt; هستند، attributeی با همان نام روی نمونه برنده می‌شود. به همین دلیل می‌توانید یک متد را فقط برای یک شیء عوض کنید (که برای mock کردن در تست‌ها خیلی به کار می‌آید):&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hello&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;lambda&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;patched&amp;quot;&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hello&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Greeter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hello&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;patched&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;hi&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;classmethod&lt;/code&gt; و &lt;code&gt;staticmethod&lt;/code&gt; هم دیسکریپتور غیرداده‌اند: &lt;code&gt;__get__&lt;/code&gt; آن‌ها به‌جای نمونه، کلاس را bind می‌کند یا اصلاً چیزی را bind نمی‌کند.&lt;/p&gt;
&lt;h2 id=&#34;ساختن-property-از-صفر&#34;&gt;ساختن property از صفر&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;property&lt;/code&gt; یک دیسکریپتور داده است که به زبان C نوشته شده، اما یک نسخهٔ کارآمد از آن به پایتون خالص در یک صفحه جا می‌شود:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyProperty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__init__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fset&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fget&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fget&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fset&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fset&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__get__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;objtype&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__set__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fset&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;AttributeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;read-only attribute&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;setter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;# a new descriptor with both functions&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Temperature&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__init__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;celsius&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;celsius&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;celsius&lt;/span&gt;

    &lt;span class=&#34;nd&#34;&gt;@MyProperty&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fahrenheit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;celsius&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;9&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;32&lt;/span&gt;

    &lt;span class=&#34;nd&#34;&gt;@fahrenheit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setter&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fahrenheit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;celsius&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;9&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Temperature&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fahrenheit&lt;/span&gt;
&lt;span class=&#34;mf&#34;&gt;212.0&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fahrenheit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;32&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;celsius&lt;/span&gt;
&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;@MyProperty&lt;/code&gt; همان &lt;code&gt;fahrenheit = MyProperty(fahrenheit)&lt;/code&gt; است. بعد &lt;code&gt;@fahrenheit.setter&lt;/code&gt; یک دیسکریپتور دوم می‌سازد که هر دو تابع را نگه می‌دارد و نام را به آن نسبت می‌دهد. چون &lt;code&gt;MyProperty&lt;/code&gt; همیشه &lt;code&gt;__set__&lt;/code&gt; را تعریف می‌کند، حتی بدون setter هم دیسکریپتور داده است؛ به همین دلیل یک property فقط‌خواندنی را نمی‌توان با مقداردهی روی نمونه پوشاند.&lt;/p&gt;
&lt;h2 id=&#34;cached_property-استفاده-آگاهانه-از-ترتیب-جستوجو&#34;&gt;cached_property: استفادهٔ آگاهانه از ترتیب جست‌وجو&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;functools.cached_property&lt;/code&gt; استفادهٔ هوشمندانه‌ای از همان قانون قبلی است. این یک دیسکریپتور &lt;strong&gt;غیرداده&lt;/strong&gt; است: در اولین دسترسی، متد شما را اجرا می‌کند و نتیجه را با همان نام در &lt;code&gt;__dict__&lt;/code&gt; نمونه ذخیره می‌کند. از آن به بعد دیکشنری نمونه در جست‌وجو برنده می‌شود و &lt;code&gt;__get__&lt;/code&gt; دیگر هرگز صدا زده نمی‌شود:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;functools&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cached_property&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Report&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;     &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__init__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;         &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;     &lt;span class=&#34;nd&#34;&gt;@cached_property&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;     &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;total&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;         &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;computing…&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;         &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Report&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;computing&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;…&lt;/span&gt;
&lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# served straight from r.__dict__&lt;/span&gt;
&lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;vars&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;rows&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;total&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;del&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;# clear the cache; the next access recomputes&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition note&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;cached_property به &lt;strong&gt;dict&lt;/strong&gt; نمونه نیاز دارد&lt;/p&gt;
&lt;p&gt;چون کش در &lt;code&gt;obj.__dict__&lt;/code&gt; نگه داشته می‌شود، &lt;code&gt;cached_property&lt;/code&gt; روی کلاس‌هایی که &lt;code&gt;__slots__&lt;/code&gt; را بدون &lt;code&gt;&#34;__dict__&#34;&lt;/code&gt; تعریف کرده‌اند کار نمی‌کند.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;باگ-کلاسیک-ذخیره-وضعیت-روی-خود-دیسکریپتور&#34;&gt;باگ کلاسیک: ذخیرهٔ وضعیت روی خودِ دیسکریپتور&lt;/h2&gt;
&lt;p&gt;برای هر attributeِ کلاس فقط &lt;strong&gt;یک&lt;/strong&gt; شیء دیسکریپتور وجود دارد که همهٔ نمونه‌ها در آن شریک‌اند. اگر داده‌های هر شیء را روی &lt;code&gt;self&lt;/code&gt; داخل دیسکریپتور ذخیره کنید، همهٔ نمونه‌ها در آن شریک می‌شوند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Broken&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__get__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;objtype&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__set__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;     &lt;span class=&#34;c1&#34;&gt;# stored on the descriptor, which every instance shares&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Account&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;balance&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Broken&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;


&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Account&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Account&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;balance&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;balance&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;balance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# 5  ← a&amp;#39;s balance was overwritten by b&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;به‌جای آن مقدارها را روی &lt;code&gt;obj&lt;/code&gt; ذخیره کنید، همان‌طور که &lt;code&gt;Positive&lt;/code&gt; با &lt;code&gt;setattr(obj, self.private_name, value)&lt;/code&gt; این کار را می‌کند.&lt;/p&gt;
&lt;div class=&#34;admonition danger&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;مراقب بازگشت بی‌پایان باشید&lt;/p&gt;
&lt;p&gt;داخل &lt;code&gt;__set__&lt;/code&gt; هرگز ننویسید &lt;code&gt;setattr(obj, self.public_name, value)&lt;/code&gt;. مقداردهی به نام &lt;em&gt;عمومی&lt;/em&gt; دوباره &lt;code&gt;__set__&lt;/code&gt; را صدا می‌زند، و این تا ابد ادامه پیدا می‌کند. همیشه با یک نام دیگر ذخیره کنید، یا مستقیم در &lt;code&gt;obj.__dict__&lt;/code&gt; بنویسید.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;کجاهای-دیگر-به-دیسکریپتورها-برمیخورید&#34;&gt;کجاهای دیگر به دیسکریپتورها برمی‌خورید&lt;/h2&gt;
&lt;p&gt;وقتی الگو را بشناسید، همه‌جا آن را می‌بینید:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;قابلیت&lt;/th&gt;
&lt;th&gt;نوع دیسکریپتور&lt;/th&gt;
&lt;th&gt;کاری که &lt;code&gt;__get__&lt;/code&gt; انجام می‌دهد&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;متدهای معمولی&lt;/td&gt;
&lt;td&gt;غیرداده&lt;/td&gt;
&lt;td&gt;یک متد bound برمی‌گرداند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;classmethod&lt;/code&gt; / &lt;code&gt;staticmethod&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;غیرداده&lt;/td&gt;
&lt;td&gt;کلاس را bind می‌کند / چیزی را bind نمی‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;property&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;داده&lt;/td&gt;
&lt;td&gt;تابع getter را صدا می‌زند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;functools.cached_property&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;غیرداده&lt;/td&gt;
&lt;td&gt;یک بار محاسبه می‌کند و در &lt;code&gt;obj.__dict__&lt;/code&gt; کش می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ورودی‌های &lt;code&gt;__slots__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;داده&lt;/td&gt;
&lt;td&gt;یک خانهٔ ثابت در حافظهٔ شیء را می‌خواند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;فیلدهای Django، ستون‌های SQLAlchemy&lt;/td&gt;
&lt;td&gt;بسته به نوع فیلد&lt;/td&gt;
&lt;td&gt;مقدار را از پایگاه داده می‌خواند، تبدیل یا ردیابی می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;حتی می‌توانید دیسکریپتورهای &lt;code&gt;__slots__&lt;/code&gt; را مستقیم ببینید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Point&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;     &lt;span class=&#34;vm&#34;&gt;__slots__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Point&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__dict__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;member&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;x&amp;#39;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Point&amp;#39;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;objects&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;دیسکریپتور&lt;/strong&gt; یک attributeِ کلاس است که کلاسش &lt;code&gt;__get__&lt;/code&gt;، &lt;code&gt;__set__&lt;/code&gt; یا &lt;code&gt;__delete__&lt;/code&gt; را تعریف کرده باشد.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;دیسکریپتورهای داده&lt;/strong&gt; (با &lt;code&gt;__set__&lt;/code&gt; یا &lt;code&gt;__delete__&lt;/code&gt;) بر دیکشنری نمونه مقدم‌اند؛ &lt;strong&gt;دیسکریپتورهای غیرداده&lt;/strong&gt; به آن می‌بازند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;متدها&lt;/strong&gt;، &lt;code&gt;property&lt;/code&gt;، &lt;code&gt;classmethod&lt;/code&gt;، &lt;code&gt;staticmethod&lt;/code&gt;، &lt;code&gt;cached_property&lt;/code&gt; و &lt;code&gt;__slots__&lt;/code&gt; همه روی دیسکریپتورها ساخته شده‌اند.&lt;/li&gt;
&lt;li&gt;با &lt;strong&gt;&lt;code&gt;__set_name__&lt;/code&gt;&lt;/strong&gt; نام attribute را بفهمید و مقدارهای هر نمونه را &lt;strong&gt;روی خودِ نمونه&lt;/strong&gt; ذخیره کنید، هرگز روی دیسکریپتور.&lt;/li&gt;
&lt;li&gt;وقتی منطق یکسانی برای attributeها (اعتبارسنجی، تبدیل، بارگذاری تنبل) در چند attribute یا چند کلاس تکرار می‌شود، سراغ یک دیسکریپتور سفارشی بروید.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;بهترین راه برای اینکه این موضوع در ذهنتان بماند: یک REPL باز کنید، دیسکریپتوری بنویسید که در هر متدش چیزی چاپ کند، و ببینید پایتون دقیقاً کِی آن را صدا می‌زند.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>حلقهٔ رویداد در جاوااسکریپت: تسک‌ها، میکروتسک‌ها و رندر</title>
      <link>https://cryo-networks.com/posts/javascript-event-loop/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/javascript-event-loop/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>جاوااسکریپت</category>
      <description>چرا یک پرامیسِ resolve‌شده همیشه زودتر از setTimeout(fn, 0) اجرا می‌شود؟ دقیقاً ببینید حلقهٔ رویداد تسک‌ها، میکروتسک‌ها و رندر صفحه را چطور زمان‌بندی می‌کند و چطور کارهای طولانی را طوری اجرا کنید که صفحه قفل نشود.</description>
      <content:encoded>&lt;p&gt;حتماً می‌دانید که &lt;code&gt;await&lt;/code&gt; تابع را متوقف می‌کند بی‌آنکه صفحه قفل شود. اما آن تابع &lt;em&gt;دقیقاً کِی&lt;/em&gt; ادامه پیدا می‌کند؟ چرا یک پرامیسِ resolve‌شده همیشه قبل از &lt;code&gt;setTimeout(fn, 0)&lt;/code&gt; اجرا می‌شود؟ و چرا پیام «در حال بارگذاری…» که درست قبل از یک محاسبهٔ سنگین تنظیم می‌کنید، گاهی هرگز روی صفحه دیده نمی‌شود؟&lt;/p&gt;
&lt;p&gt;جواب هر سه سؤال یکی است: &lt;strong&gt;حلقهٔ رویداد&lt;/strong&gt; (event loop). وقتی بتوانید آن را در ذهنتان اجرا کنید، یک دسته از باگ‌های زمان‌بندی، تست‌های ناپایدار و رابط‌های کاربریِ کُند دیگر رازآلود نیستند. این مقاله فرض می‌کند با پرامیس‌ها و &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; راحت هستید؛ اگر نه، از &lt;a href=&#34;/posts/javascript-async-await/&#34;&gt;درک async/await در جاوااسکریپت&lt;/a&gt; شروع کنید.&lt;/p&gt;
&lt;h2 id=&#34;اجزای-اصلی&#34;&gt;اجزای اصلی&lt;/h2&gt;
&lt;p&gt;جاوااسکریپت در مرورگر روی یک رشتهٔ اصلی (main thread) اجرا می‌شود و این رشته فقط کد شما را اجرا نمی‌کند؛ ورودی‌های کاربر را هم پردازش می‌کند و صفحه را هم رسم می‌کند. چهار چیز در این رشته شریک‌اند:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;پشتهٔ فراخوانی&lt;/strong&gt; (call stack): توابعی که همین الان در حال اجرا هستند. حلقهٔ رویداد فقط وقتی وارد عمل می‌شود که پشته خالی باشد.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;صف تسک‌ها&lt;/strong&gt; (task queue): واحدهای کاملِ کار که منتظر نوبت‌اند؛ مثل callbackِ یک &lt;code&gt;setTimeout&lt;/code&gt;، یک هندلر کلیک یا یک &lt;code&gt;postMessage&lt;/code&gt; از یک worker. (مستندات به این‌ها &lt;em&gt;task&lt;/em&gt; می‌گویند؛ اسم &lt;em&gt;macrotask&lt;/em&gt; را هم زیاد می‌بینید.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;صف میکروتسک‌ها&lt;/strong&gt; (microtask queue): کارهای کوچکِ پیگیری، که بیشترشان واکنش‌های پرامیس هستند (callbackهای &lt;code&gt;.then()&lt;/code&gt; و کدِ بعد از &lt;code&gt;await&lt;/code&gt;)، به‌علاوهٔ &lt;code&gt;queueMicrotask()&lt;/code&gt; و callbackهای &lt;code&gt;MutationObserver&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;مراحل رندر&lt;/strong&gt;: callbackهای &lt;code&gt;requestAnimationFrame&lt;/code&gt; و بعد محاسبهٔ استایل، چیدمان (layout) و رسم (paint).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;یک-دور-از-حلقه&#34;&gt;یک دور از حلقه&lt;/h2&gt;
&lt;p&gt;اگر جزئیات را کنار بگذاریم، مرورگر این کار را تا ابد تکرار می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;task&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;taskQueue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;takeOldest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;task&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;task&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 1. exactly ONE task&lt;/span&gt;

&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;microtaskQueue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 2. EVERY microtask,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;microtaskQueue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;shift&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;());&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;           &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//    including ones added meanwhile&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;isTimeToRender&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 3. maybe a frame&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;runAnimationFrameCallbacks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;updateStyleLayoutAndPaint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;هر دور از حلقهٔ رویداد یک تسک را اجرا می‌کند، بعد صف میکروتسک‌ها را خالی می‌کند و اگر وقتش رسیده باشد یک فریم رندر می‌کند&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;کل ماجرا در یک عدم‌تقارن است: حلقه هر بار &lt;strong&gt;فقط یک&lt;/strong&gt; تسک برمی‌دارد، اما صف میکروتسک‌ها را &lt;strong&gt;کاملاً&lt;/strong&gt; خالی می‌کند؛ حتی اگر میکروتسک‌ها مدام میکروتسک‌های تازه اضافه کنند. رندر فقط &lt;em&gt;بین&lt;/em&gt; تسک‌ها انجام می‌شود، آن هم فقط وقتی نمایشگر آمادهٔ فریم تازه است (در یک صفحهٔ ۶۰ هرتزی تقریباً هر ۱۶٫۷ میلی‌ثانیه).&lt;/p&gt;
&lt;div class=&#34;admonition note&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;اسکریپت شما هم یک تسک است&lt;/p&gt;
&lt;p&gt;اجرای اولیهٔ یک &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; خودش یک تسک است. به همین دلیل callbackهای پرامیسی که در حین آن ساخته می‌شوند، به محض تمام شدن اسکریپت و قبل از هر تایمری اجرا می‌شوند.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;خروجی-را-پیشبینی-کنید&#34;&gt;خروجی را پیش‌بینی کنید&lt;/h2&gt;
&lt;p&gt;این یک معمای کلاسیک است. قبل از خواندن جواب، ترتیب را خودتان حدس بزنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;script start&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;nx&#34;&gt;setTimeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;timeout&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;then 1&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;then 2&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;

&lt;span class=&#34;nx&#34;&gt;queueMicrotask&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;microtask&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;async start&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;async after await&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;})();&lt;/span&gt;

&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;script end&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;script start
async start
script end
then 1
microtask
async after await
then 2
timeout&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;قدم‌به‌قدم:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;اول کد همگام اجرا می‌شود: &lt;code&gt;script start&lt;/code&gt;، بعد &lt;code&gt;async start&lt;/code&gt; (یک تابع async تا اولین &lt;code&gt;await&lt;/code&gt; به‌صورت همگام اجرا می‌شود) و بعد &lt;code&gt;script end&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;در همین حین سه میکروتسک به ترتیب در صف قرار گرفتند: &lt;code&gt;then 1&lt;/code&gt;، &lt;code&gt;microtask&lt;/code&gt; و ادامهٔ تابع async. اما callbackِ تایمر به صف &lt;strong&gt;تسک‌ها&lt;/strong&gt; رفت.&lt;/li&gt;
&lt;li&gt;تسکِ اسکریپت تمام می‌شود، پس صف میکروتسک‌ها خالی می‌شود. اجرای &lt;code&gt;then 1&lt;/code&gt; پرامیس بعدیِ زنجیره را resolve می‌کند و &lt;code&gt;then 2&lt;/code&gt; را به &lt;em&gt;انتهای&lt;/em&gt; صف اضافه می‌کند. به همین دلیل &lt;code&gt;then 2&lt;/code&gt; بعد از &lt;code&gt;async after await&lt;/code&gt; می‌آید.&lt;/li&gt;
&lt;li&gt;فقط وقتی صف میکروتسک‌ها خالی شد، حلقه سراغ تسک بعدی می‌رود: تایمر.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;معنی &lt;code&gt;setTimeout(fn, 0)&lt;/code&gt; این است: «&lt;code&gt;fn&lt;/code&gt; را در یک &lt;em&gt;تسکِ آینده&lt;/em&gt; اجرا کن»، نه «همین الان اجرایش کن». هر میکروتسکی که از قبل در صف است، و هر میکروتسکی که &lt;em&gt;آن‌ها&lt;/em&gt; به صف اضافه می‌کنند، زودتر اجرا می‌شود.&lt;/p&gt;
&lt;h2 id=&#34;میکروتسکها-میتوانند-صفحه-را-گرسنه-نگه-دارند&#34;&gt;میکروتسک‌ها می‌توانند صفحه را گرسنه نگه دارند&lt;/h2&gt;
&lt;p&gt;چون حلقه تا وقتی صف میکروتسک‌ها خالی نشده از مرحلهٔ ۲ بیرون نمی‌آید، میکروتسکی که مدام میکروتسک دیگری زمان‌بندی کند، هرگز به صفحه اجازهٔ رندر یا پاسخ‌گویی نمی‌دهد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;spinForever&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;spinForever&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// freezes the tab: rendering never gets a turn&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;اگر پرامیس را با یک تایمر عوض کنید، صفحه پاسخ‌گو می‌ماند؛ چون هر callbackِ تایمر یک تسک جداست و حلقه می‌تواند بینِ آن‌ها رندر کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;spinPolitely&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;setTimeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;spinPolitely&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;           &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// one task per call: the browser can paint in between&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;setTimeout(fn, 0) واقعاً صفر نیست&lt;/p&gt;
&lt;p&gt;وقتی تایمرها پنج لایه تودرتو شوند، مرورگرها تأخیر را دست‌کم ۴ میلی‌ثانیه در نظر می‌گیرند، و در تب‌های پس‌زمینه تایمرها را خیلی بیشتر کُند می‌کنند. هیچ‌وقت برای زمان‌بندیِ دقیق به تایمرها تکیه نکنید.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;چرا-پیام-در-حال-پردازش-هرگز-نمایش-داده-نمیشود&#34;&gt;چرا پیام «در حال پردازش» هرگز نمایش داده نمی‌شود&lt;/h2&gt;
&lt;p&gt;این رایج‌ترین باگ حلقهٔ رویداد در دنیای واقعی است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nx&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addEventListener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;textContent&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Crunching numbers…&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;crunchNumbers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                 &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// synchronous, takes ~2 seconds&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;textContent&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Done!&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;کاربر هرگز متن «Crunching numbers…» را نمی‌بیند. DOM به‌روز &lt;em&gt;شده است&lt;/em&gt;، اما رسم صفحه فقط بین تسک‌ها انجام می‌شود و هندلر کلیک یک تسکِ طولانی است. وقتی نوبت رسم برسد، متن دیگر «Done!» شده است. در این دو ثانیه صفحه همهٔ کلیک‌ها و کلیدها را هم نادیده می‌گیرد.&lt;/p&gt;
&lt;p&gt;راه‌حل این است که کار طولانی را تکه‌تکه کنید و بین تکه‌ها کنترل را به حلقهٔ رویداد &lt;strong&gt;واگذار&lt;/strong&gt; کنید (yield). این واگذاری باید یک &lt;em&gt;تسک&lt;/em&gt; تازه بسازد: &lt;code&gt;await Promise.resolve()&lt;/code&gt; فقط یک میکروتسک در صف می‌گذارد، پس هرگز به مرورگر فرصت رسم نمی‌دهد.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;yieldToMain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;globalThis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;scheduler&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;?&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;yield&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;scheduler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;yield&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                              &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// newer browsers&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;ow&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;setTimeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// works everywhere&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;processAll&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;lastYield&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;performance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;

&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;processItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;performance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;lastYield&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// a &amp;quot;long task&amp;quot; is anything over 50 ms&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;yieldToMain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                      &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// let the browser paint and handle input&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;lastYield&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;performance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;حالا پیام بارگذاری نمایش داده می‌شود، کلیک‌ها پردازش می‌شوند و کار همچنان سریع تمام می‌شود، چون فقط هر ۵۰ میلی‌ثانیه یک بار کنترل را واگذار می‌کند، نه بعد از هر آیتم. هرجا &lt;code&gt;scheduler.yield()&lt;/code&gt; در دسترس باشد انتخاب بهتری است: مرورگر به ادامهٔ کار شما نسبت به بقیهٔ تسک‌های منتظر اولویت می‌دهد، پس کدهای دیگر نمی‌توانند مدام جلوی کار شما بپرند.&lt;/p&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;وقتی تکه‌تکه کردن کافی نیست&lt;/p&gt;
&lt;p&gt;اگر خودِ کار چند ثانیه محاسبهٔ خالص است (مثل پردازش یک فایل خیلی بزرگ یا پردازش تصویر)، آن را به یک &lt;strong&gt;Web Worker&lt;/strong&gt; منتقل کنید. هر worker رشته و حلقهٔ رویداد خودش را دارد، پس رشتهٔ اصلی آزاد می‌ماند.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;requestanimationframe-کار-در-لحظه-درست&#34;&gt;requestAnimationFrame: کار در لحظهٔ درست&lt;/h2&gt;
&lt;p&gt;callbackهای &lt;code&gt;requestAnimationFrame&lt;/code&gt; در مرحلهٔ ۳ و درست قبل از رسم صفحه اجرا می‌شوند. به همین دلیل جای درستِ به‌روزرسانی‌های بصری هستند: دقیقاً یک بار در هر فریم اجرا می‌شوید؛ نه دو بار بین دو رسم، و نه وسط یک رسم.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;animate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;box&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;transform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`translateX(&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;px)`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;requestAnimationFrame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;animate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// schedule the next frame&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;nx&#34;&gt;requestAnimationFrame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;animate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;اگر همین انیمیشن را با &lt;code&gt;setTimeout(animate, 16)&lt;/code&gt; پیش ببرید، با نمایشگر هماهنگ نمی‌ماند؛ بعضی فریم‌ها دو به‌روزرسانی می‌گیرند و بعضی هیچ، و این همان لرزشی است که کاربر حس می‌کند.&lt;/p&gt;
&lt;h2 id=&#34;یک-نکته-ظریف-میکروتسکها-بین-شنوندههای-رویداد&#34;&gt;یک نکتهٔ ظریف: میکروتسک‌ها بین شنونده‌های رویداد&lt;/h2&gt;
&lt;p&gt;میکروتسک‌ها هر بار که پشتهٔ فراخوانی خالی می‌شود اجرا می‌شوند، نه فقط در پایان یک تسک. به دو شنونده روی یک دکمه نگاه کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nx&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addEventListener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;microtask 1&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;listener 1&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;

&lt;span class=&#34;nx&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addEventListener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;microtask 2&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;listener 2&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;عامل اجرا&lt;/th&gt;
&lt;th&gt;خروجی&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;کلیکِ واقعیِ کاربر&lt;/td&gt;
&lt;td&gt;&lt;code&gt;listener 1&lt;/code&gt;، &lt;code&gt;microtask 1&lt;/code&gt;، &lt;code&gt;listener 2&lt;/code&gt;، &lt;code&gt;microtask 2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;button.click()&lt;/code&gt; در کد&lt;/td&gt;
&lt;td&gt;&lt;code&gt;listener 1&lt;/code&gt;، &lt;code&gt;listener 2&lt;/code&gt;، &lt;code&gt;microtask 1&lt;/code&gt;، &lt;code&gt;microtask 2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;وقتی کاربر کلیک می‌کند، مرورگر هر شنونده را با پشتهٔ خالی صدا می‌زند، پس میکروتسک‌ها بین آن‌ها اجرا می‌شوند. اما وقتی &lt;em&gt;کد شما&lt;/em&gt; &lt;code&gt;button.click()&lt;/code&gt; را صدا می‌زند، کد شما هنوز روی پشته است، پس همهٔ میکروتسک‌ها منتظر می‌مانند تا هر دو شنونده تمام شوند. اگر تستی که کلیک را شبیه‌سازی می‌کند با صفحهٔ واقعی فرق داشت، این نکته را به یاد بیاورید.&lt;/p&gt;
&lt;h2 id=&#34;nodejs-دو-صف-دیگر-هم-دارد&#34;&gt;Node.js دو صف دیگر هم دارد&lt;/h2&gt;
&lt;p&gt;Node.js همین مدل را دارد (هر بار یک تسک، و خالی کردن میکروتسک‌ها بعد از هر callback) اما دو ابزار زمان‌بندیِ مخصوص به خودش را هم اضافه می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nx&#34;&gt;setTimeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;timeout&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;setImmediate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;immediate&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;promise&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;process&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;nextTick&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;nextTick&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;اگر این کد را به‌صورت یک اسکریپت CommonJS اجرا کنید، اول &lt;code&gt;nextTick&lt;/code&gt;، بعد &lt;code&gt;promise&lt;/code&gt; و در آخر &lt;code&gt;timeout&lt;/code&gt; و &lt;code&gt;immediate&lt;/code&gt; چاپ می‌شوند؛ ترتیبِ این دو آخری ممکن است از اجرایی به اجرای دیگر عوض شود.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;callbackهای &lt;code&gt;process.nextTick()&lt;/code&gt; &lt;strong&gt;قبل از&lt;/strong&gt; میکروتسک‌های پرامیس اجرا می‌شوند. با احتیاط از آن استفاده کنید: فراخوانی بازگشتیِ &lt;code&gt;nextTick&lt;/code&gt; هم درست مثل میکروتسک‌های بازگشتی، حلقه را گرسنه نگه می‌دارد.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setImmediate()&lt;/code&gt; در یک مرحلهٔ مخصوص بعد از callbackهای I/O اجرا می‌شود. داخل یک callbackِ I/O همیشه قبل از &lt;code&gt;setTimeout(fn, 0)&lt;/code&gt; اجرا می‌شود؛ اما در اسکریپت اصلی ترتیبشان تضمینی نیست.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;admonition note&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;ماژول‌های ES&lt;/p&gt;
&lt;p&gt;در یک ماژول ES (فایل &lt;code&gt;.mjs&lt;/code&gt;) ممکن است &lt;code&gt;promise&lt;/code&gt; قبل از &lt;code&gt;nextTick&lt;/code&gt; چاپ شود، چون خودِ بدنهٔ ماژول از داخل صف میکروتسک‌ها اجرا می‌شود. کدی ننویسید که به ترتیبِ دقیقِ &lt;code&gt;nextTick&lt;/code&gt; و پرامیس‌ها وابسته باشد.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;حلقهٔ رویداد &lt;strong&gt;یک تسک&lt;/strong&gt; را اجرا می‌کند، بعد &lt;strong&gt;همهٔ میکروتسک‌ها&lt;/strong&gt; را، بعد اگر وقت فریم تازه رسیده باشد &lt;strong&gt;رندر&lt;/strong&gt; می‌کند و دوباره تکرار می‌کند.&lt;/li&gt;
&lt;li&gt;callbackهای پرامیس، کدِ بعد از &lt;code&gt;await&lt;/code&gt; و &lt;code&gt;queueMicrotask()&lt;/code&gt; &lt;strong&gt;میکروتسک&lt;/strong&gt; هستند: همیشه قبل از تایمر، رویداد یا رسمِ بعدی اجرا می‌شوند.&lt;/li&gt;
&lt;li&gt;میکروتسکی که تا ابد میکروتسک زمان‌بندی کند &lt;strong&gt;صفحه را قفل می‌کند&lt;/strong&gt;؛ تایمرها این کار را نمی‌کنند، چون هر کدام یک تسک جداست.&lt;/li&gt;
&lt;li&gt;کارهای همگامِ طولانی جلوی رسم صفحه و پردازش ورودی را می‌گیرند. آن‌ها را تکه‌تکه کنید و با &lt;code&gt;setTimeout&lt;/code&gt; یا &lt;code&gt;scheduler.yield()&lt;/code&gt; کنترل را واگذار کنید. &lt;code&gt;await Promise.resolve()&lt;/code&gt; کنترل را واگذار &lt;strong&gt;نمی‌کند&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;برای به‌روزرسانی‌های بصری از &lt;strong&gt;&lt;code&gt;requestAnimationFrame&lt;/code&gt;&lt;/strong&gt; و برای محاسبات سنگین از &lt;strong&gt;Web Worker&lt;/strong&gt; استفاده کنید.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;دفعهٔ بعد که چیزی «به ترتیب اشتباه» اجرا شد، از خودتان بپرسید: &lt;em&gt;این یک تسک است یا میکروتسک، و چه چیزهای دیگری در همان صف هستند؟&lt;/em&gt;&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>جست‌وجوی دودویی بدون باگ‌های یکی‌کم‌ویکی‌زیاد</title>
      <link>https://cryo-networks.com/posts/binary-search-boundaries/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/binary-search-boundaries/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>الگوریتم‌ها</category>
      <description>جست‌وجوی دودویی را راحت می‌شود توضیح داد و به‌طرز عجیبی راحت می‌شود اشتباه نوشت. یک «ناوردا» یاد بگیرید که آن را هر بار درست از آب درمی‌آورد، اولین و آخرین موقعیت را پیدا کنید و جست‌وجوی دودویی را به‌جای آرایه روی جواب‌ها اجرا کنید.</description>
      <content:encoded>&lt;p&gt;جست‌وجوی دودویی (binary search) در یک جمله خلاصه می‌شود: &lt;em&gt;به آیتمِ وسط نگاه کن، بعد نیمه‌ای را که نمی‌تواند چیزِ موردنظرت را داشته باشد دور بریز.&lt;/em&gt; هر مرحله بازهٔ باقی‌مانده را نصف می‌کند؛ پس حتی یک میلیارد آیتمِ مرتب فقط حدود ۳۰ مرحله لازم دارد. این یعنی &lt;strong&gt;O(log n)&lt;/strong&gt;؛ اگر Big-O برایتان تازه است، از &lt;a href=&#34;/posts/big-o-notation-explained/&#34;&gt;نماد Big-O با کد واقعی&lt;/a&gt; شروع کنید.&lt;/p&gt;
&lt;p&gt;درست نوشتنش اما داستان دیگری است. جان بنتلی در کتاب &lt;em&gt;Programming Pearls&lt;/em&gt; می‌گوید وقتی از برنامه‌نویس‌های حرفه‌ای خواست جست‌وجوی دودویی بنویسند، حدود ۹۰ درصدشان باگ داشتند. نسخهٔ کتابخانهٔ استاندارد جاوا هم یک باگ سرریز (overflow) داشت که حدود نُه سال کسی متوجهش نشد. مقصرهای همیشگی خطاهای یکی‌کم‌ویکی‌زیاد (off-by-one) هستند: &lt;code&gt;&amp;lt;&lt;/code&gt; یا &lt;code&gt;&amp;lt;=&lt;/code&gt;؟ &lt;code&gt;mid&lt;/code&gt; یا &lt;code&gt;mid + 1&lt;/code&gt;؟ حلقه کِی تمام می‌شود؟&lt;/p&gt;
&lt;p&gt;این مقاله یک الگو به شما می‌دهد که جواب این سؤال‌ها را خودش می‌دهد، و نشان می‌دهد تا کجا می‌شود از آن استفاده کرد.&lt;/p&gt;
&lt;h2 id=&#34;سؤالی-که-باید-پرسید&#34;&gt;سؤالی که باید پرسید&lt;/h2&gt;
&lt;p&gt;«آیا &lt;code&gt;x&lt;/code&gt; در لیست هست؟» ضعیف‌ترین شکلِ جست‌وجوی دودویی است. سؤالِ بسیار مفیدتر این است:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;اولین آیتمی که بزرگ‌تر یا مساوی &lt;code&gt;x&lt;/code&gt; است کجاست؟&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;به این معمولاً &lt;strong&gt;کران پایین&lt;/strong&gt; (lower bound) می‌گویند. چند سؤال را هم‌زمان جواب می‌دهد: آیا &lt;code&gt;x&lt;/code&gt; وجود دارد، اگر چند بار تکرار شده از کجا شروع می‌شود، و برای مرتب ماندنِ لیست باید کجا درج شود.&lt;/p&gt;
&lt;h2 id=&#34;یک-الگو-بازه-نیمهباز&#34;&gt;یک الگو: بازهٔ نیمه‌باز&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;lower_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;&amp;quot;&amp;quot;&amp;quot;Index of the first item &amp;gt;= x, or len(a) if every item is smaller.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;            &lt;span class=&#34;c1&#34;&gt;# invariant: the answer is between lo and hi (inclusive)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# a[mid] is too small, so the answer is to its right&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;              &lt;span class=&#34;c1&#34;&gt;# a[mid] could be the answer: keep it in range&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;هر خط از &lt;strong&gt;ناوردا&lt;/strong&gt; (invariant) نتیجه می‌شود؛ همان جمله‌ای که در کامنت آمده و در تمام اجرای حلقه درست می‌ماند:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hi&lt;/code&gt; از &lt;code&gt;len(a)&lt;/code&gt; شروع می‌شود، نه &lt;code&gt;len(a) - 1&lt;/code&gt;، چون «هیچ آیتمی به اندازهٔ کافی بزرگ نیست» هم جوابِ معتبری است.&lt;/li&gt;
&lt;li&gt;اگر &lt;code&gt;a[mid] &amp;lt; x&lt;/code&gt; باشد، &lt;code&gt;mid&lt;/code&gt; و همهٔ آیتم‌های قبل از آن کوچک‌اند؛ پس جواب دست‌کم &lt;code&gt;mid + 1&lt;/code&gt; است.&lt;/li&gt;
&lt;li&gt;در غیر این صورت &lt;code&gt;a[mid] &amp;gt;= x&lt;/code&gt; است، پس &lt;code&gt;mid&lt;/code&gt; &lt;em&gt;ممکن است&lt;/em&gt; جواب باشد. نمی‌توانیم از آن بگذریم؛ پس &lt;code&gt;hi = mid&lt;/code&gt;، نه &lt;code&gt;mid - 1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;بازه در هر دور کوچک‌تر می‌شود (&lt;code&gt;mid&lt;/code&gt; همیشه از &lt;code&gt;hi&lt;/code&gt; کمتر است)، پس حلقه تمام می‌شود. وقتی &lt;code&gt;lo == hi&lt;/code&gt; شد، فقط یک نامزد باقی مانده و همان جواب است.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;بیایید جست‌وجوی &lt;code&gt;23&lt;/code&gt; را دنبال کنیم:&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;lower_bound در جست‌وجوی ۲۳: بازه از کلِ لیست شروع می‌شود، بعد به اندیس‌های ۰ تا ۵، ۳ تا ۵، ۳ تا ۴ و در آخر به اندیس ۴، یعنی اولین ۲۳، می‌رسد&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;42&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;56&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;70&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;lower_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# 4  (the first 23)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;lower_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# 4  (20 would be inserted before the first 23)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;lower_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# 10 (bigger than everything: len(a))&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;lower_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;# 0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;حالا بررسیِ عضویت یک خط است، بدون هیچ حالت خاصی داخل حلقه:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;contains&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lower_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;کران-بالا-و-شمارش&#34;&gt;کران بالا و شمارش&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;&lt;/code&gt; را به &lt;code&gt;&amp;lt;=&lt;/code&gt; تغییر دهید تا &lt;strong&gt;کران بالا&lt;/strong&gt; (upper bound) را بگیرید: اولین آیتمی که اکیداً از &lt;code&gt;x&lt;/code&gt; بزرگ‌تر است.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;upper_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;این دو با هم کلِ بلوکِ آیتم‌های مساوی را به شما می‌دهند؛ پس شمردنِ تکراری‌ها در یک لیست مرتب O(log n) طول می‌کشد، نه O(n):&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;upper_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lower_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# 2&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;upper_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# [23, 23]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;پایتون این‌ها را از قبل دارد&lt;/p&gt;
&lt;p&gt;ماژول &lt;code&gt;bisect&lt;/code&gt; دقیقاً همین است: &lt;code&gt;bisect.bisect_left(a, x)&lt;/code&gt; همان &lt;code&gt;lower_bound&lt;/code&gt; است و &lt;code&gt;bisect.bisect_right(a, x)&lt;/code&gt; همان &lt;code&gt;upper_bound&lt;/code&gt;. &lt;code&gt;bisect.insort(a, x)&lt;/code&gt; آیتم را طوری درج می‌کند که لیست مرتب بماند. از پایتون ۳٫۱۰ این توابع &lt;code&gt;key=&lt;/code&gt; هم می‌گیرند، مثلاً &lt;code&gt;bisect_left(users, 35, key=lambda u: u.age)&lt;/code&gt;. در کد واقعی از این‌ها استفاده کنید؛ وقتی به نسخهٔ کلی‌ترِ پایین نیاز دارید، خودتان بنویسید.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;نسخه-کلی-اولین-true&#34;&gt;نسخهٔ کلی: اولین True&lt;/h2&gt;
&lt;p&gt;دوباره به آن دو تابع نگاه کنید. تنها چیزی که فرق می‌کند یک شرط است که مدتی &lt;code&gt;False&lt;/code&gt; است و از یک جایی به بعد &lt;code&gt;True&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;index:      0      1      2      3      4     5     6     ...
a[i] &amp;gt;= 23: False  False  False  False  True  True  True  ...
                                        ↑ the answer&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;پس جست‌وجوی دودویی در واقع &lt;strong&gt;مرزِ یک سؤالِ بله/نه&lt;/strong&gt; را پیدا می‌کند، به شرطی که جواب‌ها هرگز از &lt;code&gt;True&lt;/code&gt; به &lt;code&gt;False&lt;/code&gt; برنگردند. این ارزشِ یک تابعِ جداگانه را دارد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;first_true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pred&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;&amp;quot;&amp;quot;&amp;quot;Smallest i in [lo, hi) where pred(i) is True, or hi if there is none.&lt;/span&gt;
&lt;span class=&#34;sd&#34;&gt;    pred must be False, False, ..., True, True over that range.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pred&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;lower_bound(a, x)&lt;/code&gt; فقط همان &lt;code&gt;first_true(0, len(a), lambda i: a[i] &amp;gt;= x)&lt;/code&gt; است. اما شرط اصلاً به آرایه نیازی ندارد.&lt;/p&gt;
&lt;h2 id=&#34;جستوجوی-دودویی-روی-جواب&#34;&gt;جست‌وجوی دودویی روی جواب&lt;/h2&gt;
&lt;p&gt;ریشهٔ دومِ صحیحِ &lt;code&gt;n&lt;/code&gt; بزرگ‌ترین &lt;code&gt;r&lt;/code&gt; است که &lt;code&gt;r * r &amp;lt;= n&lt;/code&gt;. به بیان دیگر، یکی کمتر از اولین &lt;code&gt;r&lt;/code&gt; است که &lt;code&gt;r * r &amp;gt; n&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;isqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;first_true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;isqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# 7&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;isqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;# 1000000, in about 40 steps&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;این ترفند یک خانوادهٔ کامل از مسئله‌های «کمترین مقداری که جواب می‌دهد را پیدا کن» را حل می‌کند. فرض کنید یک کامیون باید بسته‌ها را &lt;strong&gt;به ترتیب&lt;/strong&gt; تحویل دهد، روزی &lt;code&gt;capacity&lt;/code&gt; کیلوگرم بار ببرد و همه‌چیز باید ظرف &lt;code&gt;days&lt;/code&gt; روز تحویل داده شود. کمترین ظرفیتی که کافی است چقدر است؟&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;days_needed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;weights&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;capacity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;days&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;load&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;w&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;weights&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;load&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;w&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;capacity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;# doesn&amp;#39;t fit: start a new day&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;days&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;load&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;load&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;w&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;min_capacity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;weights&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;weights&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;weights&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;first_true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days_needed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;weights&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;min_capacity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# 6: [3, 2] [2, 4] [1, 4]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;پیدا کردنِ مستقیمِ ظرفیت سخت است، اما &lt;em&gt;بررسیِ&lt;/em&gt; یک ظرفیت آسان است، و جواب یکنوا (monotonic) است: اگر ظرفیت ۶ کافی باشد، ۷ هم کافی است. جست‌وجوی دودویی یک بررسیِ آسان را به یک جست‌وجوی سریع تبدیل می‌کند: O(n log S) به‌جای امتحان کردنِ تک‌تکِ ظرفیت‌ها تا &lt;code&gt;S = sum(weights)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;چند جزئیاتِ مرزی که همه از همان الگو نتیجه می‌شوند: ظرفیت نمی‌تواند از سنگین‌ترین بسته کمتر باشد، پس &lt;code&gt;lo = max(weights)&lt;/code&gt;. &lt;code&gt;hi = sum(weights)&lt;/code&gt; را می‌دهیم با اینکه &lt;code&gt;first_true&lt;/code&gt; هرگز خودِ &lt;code&gt;hi&lt;/code&gt; را امتحان نمی‌کند: اگر هیچ ظرفیتِ کوچک‌تری جواب ندهد، &lt;code&gt;hi&lt;/code&gt; را برمی‌گرداند، که درست است، چون بردنِ همه‌چیز در یک روز همیشه شدنی است.&lt;/p&gt;
&lt;div class=&#34;admonition note&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;یکی را از قبل می‌شناسید: git bisect&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git bisect&lt;/code&gt; دقیقاً همین الگوریتم روی کامیت‌هاست: سؤال این است که «آیا باگ در این کامیت هست؟» و جواب‌ها دقیقاً در یک نقطه از «نه» به «بله» تغییر می‌کنند. هزار کامیت فقط حدود ۱۰ آزمایش لازم دارد.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;باگهایی-که-باید-حواستان-باشد&#34;&gt;باگ‌هایی که باید حواستان باشد&lt;/h2&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;باگ&lt;/th&gt;
&lt;th&gt;چه چیزی خراب می‌شود&lt;/th&gt;
&lt;th&gt;راه‌حل&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hi = len(a) - 1&lt;/code&gt; همراه با &lt;code&gt;while lo &amp;lt; hi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;len(a)&lt;/code&gt; هرگز برگردانده نمی‌شود و آخرین آیتم هرگز بررسی نمی‌شود&lt;/td&gt;
&lt;td&gt;یک قرارداد انتخاب کنید (ما بازهٔ نیمه‌باز &lt;code&gt;[lo, hi)&lt;/code&gt; را برداشتیم) و به آن پایبند بمانید&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lo = mid&lt;/code&gt; به‌جای &lt;code&gt;mid + 1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;وقتی &lt;code&gt;hi = lo + 1&lt;/code&gt; باشد، &lt;code&gt;mid == lo&lt;/code&gt; تا ابد: حلقهٔ بی‌پایان&lt;/td&gt;
&lt;td&gt;هر شاخه باید بازه را کوچک‌تر کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hi = mid - 1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;وقتی &lt;code&gt;a[mid]&lt;/code&gt; خودش جواب است، ممکن است از آن رد شود&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mid&lt;/code&gt; را فقط وقتی کنار بگذارید که قطعاً جواب نیست&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;(lo + hi) / 2&lt;/code&gt; در جاوا، C، Go و…&lt;/td&gt;
&lt;td&gt;روی آرایه‌های بزرگ، &lt;code&gt;lo + hi&lt;/code&gt; می‌تواند از یک int سی‌ودوبیتی سرریز کند&lt;/td&gt;
&lt;td&gt;از &lt;code&gt;lo + (hi - lo) / 2&lt;/code&gt; استفاده کنید (عددهای صحیح پایتون سرریز نمی‌شوند)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;جست‌وجو در داده‌های نامرتب&lt;/td&gt;
&lt;td&gt;بی‌صدا جوابی برمی‌گرداند که معقول به نظر می‌رسد اما غلط است&lt;/td&gt;
&lt;td&gt;اول مرتب کنید، یا مطمئن شوید شرط واقعاً یکنواست&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;آن-را-با-نسخه-کند-بسنجید&#34;&gt;آن را با نسخهٔ کُند بسنجید&lt;/h2&gt;
&lt;p&gt;جست‌وجوی دودویی نامزدِ کاملی برای &lt;strong&gt;تستِ مقایسه با روش brute-force&lt;/strong&gt; است: یک پیمایشِ خطی به‌وضوح درست است، پس روی هزاران ورودیِ تصادفی، از جمله لیست‌های خالی و تکراری‌ها، با آن مقایسه کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;random&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10_000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sorted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;random&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;randint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;random&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;randint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;random&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;randint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;22&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;expected&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;next&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;v&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;enumerate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;v&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lower_bound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expected&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;مقدارهای کوچک (۰ تا ۲۰) تعداد زیادی تکراری و حالت مرزی می‌سازند. این نوع تست همهٔ باگ‌های جدول بالا را در کسری از ثانیه پیدا می‌کند.&lt;/p&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;به‌جای «آیا x اینجاست؟» بپرسید &lt;strong&gt;«اولین آیتمِ ≥ x کجاست؟»&lt;/strong&gt; (کران پایین).&lt;/li&gt;
&lt;li&gt;از &lt;strong&gt;بازهٔ نیمه‌باز&lt;/strong&gt; &lt;code&gt;[lo, hi)&lt;/code&gt; با &lt;code&gt;while lo &amp;lt; hi&lt;/code&gt;، &lt;code&gt;lo = mid + 1&lt;/code&gt; و &lt;code&gt;hi = mid&lt;/code&gt; استفاده کنید. هر مرحله بازه را کوچک‌تر می‌کند و در پایان &lt;code&gt;lo&lt;/code&gt; جواب است.&lt;/li&gt;
&lt;li&gt;جست‌وجوی دودویی &lt;strong&gt;مرزِ هر سؤالِ بله/نهِ یکنوا&lt;/strong&gt; را پیدا می‌کند؛ پس می‌توانید روی جواب‌ها (ظرفیت‌ها، اندازه‌ها، زمان‌ها، کامیت‌ها) جست‌وجو کنید، نه فقط روی آرایه‌ها.&lt;/li&gt;
&lt;li&gt;در پایتون اول سراغ &lt;code&gt;bisect&lt;/code&gt; بروید.&lt;/li&gt;
&lt;li&gt;با یک نسخهٔ brute-force و ورودی‌های تصادفیِ کوچک تست کنید.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
    </item>
    <item>
      <title>توابع پنجره‌ای در SQL: جمع تجمعی، رتبه‌بندی و میانگین متحرک</title>
      <link>https://cryo-networks.com/posts/sql-window-functions/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/sql-window-functions/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>SQL</category>
      <description>GROUP BY ردیف‌ها را در هم فشرده می‌کند؛ توابع پنجره‌ای روی چند ردیف محاسبه می‌کنند و همهٔ آن‌ها را نگه می‌دارند. OVER، PARTITION BY، ROW_NUMBER، RANK، LAG و قاب‌های پنجره را با مثال‌های کوچک و قابل اجرا یاد بگیرید.</description>
      <content:encoded>&lt;p&gt;دیر یا زود گزارشی چیزی می‌خواهد که از &lt;code&gt;GROUP BY&lt;/code&gt; برنمی‌آید. &lt;em&gt;هر فروش را کنار مجموعِ منطقه‌اش نشان بده.&lt;/em&gt; &lt;em&gt;فروشنده‌ها را در هر منطقه رتبه‌بندی کن.&lt;/em&gt; &lt;em&gt;درآمد این ماه را کنار ماه قبل نشان بده.&lt;/em&gt; با &lt;code&gt;GROUP BY&lt;/code&gt; برای هر گروه یک ردیف می‌گیرید و جزئیات از دست می‌رود؛ آدم‌ها معمولاً سراغ self-join، زیرکوئری یا یک حلقه در کد برنامه می‌روند.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;توابع پنجره‌ای&lt;/strong&gt; (window functions) همهٔ این‌ها را در یک کوئری حل می‌کنند. آن‌ها مقدارها را روی مجموعه‌ای از ردیف‌های مرتبط (همان &lt;em&gt;پنجره&lt;/em&gt;) محاسبه می‌کنند، &lt;strong&gt;بدون اینکه آن‌ها را در هم فشرده کنند&lt;/strong&gt;: هر ردیفِ ورودی همچنان در خروجی هست و مقدارِ محاسبه‌شده به شکل یک ستون جدید به آن اضافه می‌شود.&lt;/p&gt;
&lt;p&gt;این توابع در PostgreSQL، MySQL 8 به بعد، SQL Server، Oracle و SQLite 3.25 به بعد کار می‌کنند. مثال‌های زیر همان‌طور که هستند در SQLite اجرا می‌شوند. اگر هنوز با JOINها راحت نیستید، از &lt;a href=&#34;/posts/sql-joins-explained/&#34;&gt;JOINها در SQL با مثال‌های ساده&lt;/a&gt; شروع کنید.&lt;/p&gt;
&lt;h2 id=&#34;دادههای-نمونه-ما&#34;&gt;داده‌های نمونهٔ ما&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sales&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rep&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;TEXT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;TEXT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;INTEGER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;INSERT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INTO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sales&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;VALUES&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Ana&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;North&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;900&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Ben&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;North&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;700&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Cleo&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;North&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;700&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Dev&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;North&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Eve&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;South&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1200&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Finn&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;South&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;650&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Gus&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;South&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;300&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;monthly&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;month&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;TEXT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;revenue&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;INTEGER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;INSERT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INTO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;monthly&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;VALUES&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2026-01&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;12000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2026-02&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;15000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2026-03&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;11000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2026-04&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;18000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2026-05&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;21000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2026-06&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;19500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;مقایسه-group-by-با-پنجره&#34;&gt;مقایسهٔ GROUP BY با پنجره&lt;/h2&gt;
&lt;p&gt;این مجموعِ هر منطقه با &lt;code&gt;GROUP BY&lt;/code&gt; است. هفت ردیف وارد می‌شود و دو ردیف بیرون می‌آید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SUM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sales&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;GROUP&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;region&lt;/th&gt;
&lt;th&gt;total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;North&lt;/td&gt;
&lt;td&gt;2700&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;South&lt;/td&gt;
&lt;td&gt;2150&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;حالا همان &lt;code&gt;SUM&lt;/code&gt;، اما با یک &lt;strong&gt;&lt;code&gt;OVER&lt;/code&gt;&lt;/strong&gt; بعد از آن، که آن را به یک تابع پنجره‌ای تبدیل می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SUM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PARTITION&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region_total&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ROUND&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SUM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PARTITION&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pct_of_region&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sales&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DESC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;rep&lt;/th&gt;
&lt;th&gt;region&lt;/th&gt;
&lt;th&gt;amount&lt;/th&gt;
&lt;th&gt;region_total&lt;/th&gt;
&lt;th&gt;pct_of_region&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ana&lt;/td&gt;
&lt;td&gt;North&lt;/td&gt;
&lt;td&gt;900&lt;/td&gt;
&lt;td&gt;2700&lt;/td&gt;
&lt;td&gt;33.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ben&lt;/td&gt;
&lt;td&gt;North&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;td&gt;2700&lt;/td&gt;
&lt;td&gt;25.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cleo&lt;/td&gt;
&lt;td&gt;North&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;td&gt;2700&lt;/td&gt;
&lt;td&gt;25.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev&lt;/td&gt;
&lt;td&gt;North&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;2700&lt;/td&gt;
&lt;td&gt;14.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eve&lt;/td&gt;
&lt;td&gt;South&lt;/td&gt;
&lt;td&gt;1200&lt;/td&gt;
&lt;td&gt;2150&lt;/td&gt;
&lt;td&gt;55.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finn&lt;/td&gt;
&lt;td&gt;South&lt;/td&gt;
&lt;td&gt;650&lt;/td&gt;
&lt;td&gt;2150&lt;/td&gt;
&lt;td&gt;30.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gus&lt;/td&gt;
&lt;td&gt;South&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;2150&lt;/td&gt;
&lt;td&gt;14.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;هر هفت ردیف می‌مانند. &lt;code&gt;PARTITION BY region&lt;/code&gt; ردیف‌ها را مثل &lt;code&gt;GROUP BY&lt;/code&gt; گروه‌بندی می‌کند، اما به‌جای اینکه هر گروه را در یک ردیف فشرده کند، به هر ردیف دسترسی به کلِ گروهش را می‌دهد. با یک &lt;code&gt;OVER ()&lt;/code&gt; خالی، پنجره کلِ نتیجه است.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;PARTITION BY ردیف‌ها را به یک پنجرهٔ North و یک پنجرهٔ South تقسیم می‌کند؛ هر ردیف مقدارهای خودش را نگه می‌دارد و مجموعِ پنجره‌اش به آن اضافه می‌شود، و با ORDER BY این مجموع به جمع تجمعی تبدیل می‌شود&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&#34;ساختار-over&#34;&gt;ساختار OVER&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PARTITION&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;-- which rows belong together (optional)&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;-- the order of rows inside each partition (optional)&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ROWS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BETWEEN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;-- which of those rows to use for this row (optional)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;همهٔ بخش‌ها اختیاری‌اند و هر کدام نتیجه را تغییر می‌دهد. یکی‌یکی سراغشان می‌رویم.&lt;/p&gt;
&lt;h2 id=&#34;رتبهبندی-با-row_number-rank-و-dense_rank&#34;&gt;رتبه‌بندی با ROW_NUMBER، RANK و DENSE_RANK&lt;/h2&gt;
&lt;p&gt;توابع رتبه‌بندی داخل پنجره به یک &lt;code&gt;ORDER BY&lt;/code&gt; نیاز دارند. تنها تفاوتشان در رفتار با مقدارهای مساوی است، و داده‌های ما یک تساوی دارد: Ben و Cleo هر دو ۷۰۰ فروخته‌اند.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ROW_NUMBER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DESC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row_num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RANK&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DESC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rnk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DENSE_RANK&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DESC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dense_rnk&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sales&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DESC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;rep&lt;/th&gt;
&lt;th&gt;amount&lt;/th&gt;
&lt;th&gt;row_num&lt;/th&gt;
&lt;th&gt;rnk&lt;/th&gt;
&lt;th&gt;dense_rnk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Eve&lt;/td&gt;
&lt;td&gt;1200&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ana&lt;/td&gt;
&lt;td&gt;900&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ben&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cleo&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finn&lt;/td&gt;
&lt;td&gt;650&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gus&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ROW_NUMBER&lt;/code&gt;&lt;/strong&gt; همیشه ۱، ۲، ۳، ۴… می‌دهد، بدون تساوی. اینکه Ben یا Cleo عدد ۳ را بگیرد به پایگاه داده بستگی دارد، مگر اینکه یک معیارِ دوم مثل &lt;code&gt;ORDER BY amount DESC, rep&lt;/code&gt; اضافه کنید.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;RANK&lt;/code&gt;&lt;/strong&gt; به مقدارهای مساوی یک عدد می‌دهد و بعد &lt;strong&gt;عدد را جا می‌اندازد&lt;/strong&gt;: ۳، ۳، ۵. مثل مسابقه‌ای که دو دونده با هم مدال برنز می‌گیرند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DENSE_RANK&lt;/code&gt;&lt;/strong&gt; به مقدارهای مساوی یک عدد می‌دهد و &lt;strong&gt;جا نمی‌اندازد&lt;/strong&gt;: ۳، ۳، ۴.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;n-تای-برتر-در-هر-گروه&#34;&gt;N تای برتر در هر گروه&lt;/h2&gt;
&lt;p&gt;«دو فروشندهٔ برتر در هر منطقه» یکی از رایج‌ترین سؤال‌های گزارش‌گیری است و توابع پنجره‌ای آن را ساده می‌کنند. اما نمی‌توانید مستقیماً روی یک تابع پنجره‌ای فیلتر کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rep&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sales&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ROW_NUMBER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;-- Error: misuse of window function ROW_NUMBER()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;توابع پنجره‌ای &lt;strong&gt;بعد از&lt;/strong&gt; &lt;code&gt;WHERE&lt;/code&gt;، &lt;code&gt;GROUP BY&lt;/code&gt; و &lt;code&gt;HAVING&lt;/code&gt; محاسبه می‌شوند، درست قبل از &lt;code&gt;ORDER BY&lt;/code&gt; و &lt;code&gt;LIMIT&lt;/code&gt; نهایی. پس رتبه را در یک زیرکوئری یا CTE حساب می‌کنید و بعد نتیجه را فیلتر می‌کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;WITH&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ranked&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ROW_NUMBER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PARTITION&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DESC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pos&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sales&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ranked&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pos&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;region&lt;/th&gt;
&lt;th&gt;pos&lt;/th&gt;
&lt;th&gt;rep&lt;/th&gt;
&lt;th&gt;amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;North&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Ana&lt;/td&gt;
&lt;td&gt;900&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;North&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Ben&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;South&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Eve&lt;/td&gt;
&lt;td&gt;1200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;South&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Finn&lt;/td&gt;
&lt;td&gt;650&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;اگر می‌خواهید فروشنده‌های هم‌امتیاز &lt;em&gt;هر دو&lt;/em&gt; در فهرست بیایند، به‌جای &lt;code&gt;ROW_NUMBER()&lt;/code&gt; از &lt;code&gt;RANK()&lt;/code&gt; استفاده کنید.&lt;/p&gt;
&lt;h2 id=&#34;جمع-تجمعی&#34;&gt;جمع تجمعی&lt;/h2&gt;
&lt;p&gt;به پنجرهٔ یک تابع تجمیعی &lt;code&gt;ORDER BY&lt;/code&gt; اضافه کنید تا &lt;strong&gt;تجمعی&lt;/strong&gt; شود: هر ردیف همه‌چیز را از ابتدای پارتیشن تا خودش جمع می‌زند.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;revenue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SUM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;revenue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;running_total&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;monthly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;month&lt;/th&gt;
&lt;th&gt;revenue&lt;/th&gt;
&lt;th&gt;running_total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2026-01&lt;/td&gt;
&lt;td&gt;12000&lt;/td&gt;
&lt;td&gt;12000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-02&lt;/td&gt;
&lt;td&gt;15000&lt;/td&gt;
&lt;td&gt;27000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-03&lt;/td&gt;
&lt;td&gt;11000&lt;/td&gt;
&lt;td&gt;38000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-04&lt;/td&gt;
&lt;td&gt;18000&lt;/td&gt;
&lt;td&gt;56000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-05&lt;/td&gt;
&lt;td&gt;21000&lt;/td&gt;
&lt;td&gt;77000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-06&lt;/td&gt;
&lt;td&gt;19500&lt;/td&gt;
&lt;td&gt;96500&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;با اضافه کردن &lt;code&gt;PARTITION BY&lt;/code&gt;، جمع تجمعی برای هر گروه از نو شروع می‌شود؛ مثلاً مجموعِ «از ابتدای سال تا امروز» که هر ژانویه صفر می‌شود.&lt;/p&gt;
&lt;h2 id=&#34;مقایسه-با-ردیف-قبلی-lag-و-lead&#34;&gt;مقایسه با ردیف قبلی: LAG و LEAD&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;LAG(column)&lt;/code&gt; مقدار را از ردیفِ &lt;strong&gt;قبلی&lt;/strong&gt; در پنجره برمی‌گرداند و &lt;code&gt;LEAD(column)&lt;/code&gt; از ردیفِ &lt;strong&gt;بعدی&lt;/strong&gt;. تغییرِ ماه‌به‌ماه به یک تفریقِ ساده تبدیل می‌شود:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;revenue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LAG&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;revenue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prev_month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;revenue&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LAG&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;revenue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;change&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;monthly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;month&lt;/th&gt;
&lt;th&gt;revenue&lt;/th&gt;
&lt;th&gt;prev_month&lt;/th&gt;
&lt;th&gt;change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2026-01&lt;/td&gt;
&lt;td&gt;12000&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-02&lt;/td&gt;
&lt;td&gt;15000&lt;/td&gt;
&lt;td&gt;12000&lt;/td&gt;
&lt;td&gt;3000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-03&lt;/td&gt;
&lt;td&gt;11000&lt;/td&gt;
&lt;td&gt;15000&lt;/td&gt;
&lt;td&gt;-4000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-04&lt;/td&gt;
&lt;td&gt;18000&lt;/td&gt;
&lt;td&gt;11000&lt;/td&gt;
&lt;td&gt;7000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-05&lt;/td&gt;
&lt;td&gt;21000&lt;/td&gt;
&lt;td&gt;18000&lt;/td&gt;
&lt;td&gt;3000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-06&lt;/td&gt;
&lt;td&gt;19500&lt;/td&gt;
&lt;td&gt;21000&lt;/td&gt;
&lt;td&gt;-1500&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;ماه اول ردیفِ قبلی ندارد، پس &lt;code&gt;LAG&lt;/code&gt; مقدار &lt;code&gt;NULL&lt;/code&gt; برمی‌گرداند. &lt;code&gt;LAG(revenue, 1, 0)&lt;/code&gt; به‌جای آن &lt;code&gt;0&lt;/code&gt; برمی‌گرداند، و &lt;code&gt;LAG(revenue, 12)&lt;/code&gt; دوازده ردیف عقب می‌رود که برای مقایسهٔ سال‌به‌سال به کار می‌آید.&lt;/p&gt;
&lt;h2 id=&#34;قابهای-پنجره-میانگین-متحرک&#34;&gt;قاب‌های پنجره: میانگین متحرک&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;قاب&lt;/strong&gt; (frame) تعیین می‌کند کدام ردیف‌های پارتیشن برای ردیفِ فعلی حساب شوند. میانگینِ متحرکِ سه‌ماهه از ردیف فعلی و دو ردیفِ قبل از آن استفاده می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;revenue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ROUND&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AVG&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;revenue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;month&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ROWS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BETWEEN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PRECEDING&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AND&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CURRENT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ROW&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;avg_3m&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;monthly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;month&lt;/th&gt;
&lt;th&gt;revenue&lt;/th&gt;
&lt;th&gt;avg_3m&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2026-01&lt;/td&gt;
&lt;td&gt;12000&lt;/td&gt;
&lt;td&gt;12000.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-02&lt;/td&gt;
&lt;td&gt;15000&lt;/td&gt;
&lt;td&gt;13500.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-03&lt;/td&gt;
&lt;td&gt;11000&lt;/td&gt;
&lt;td&gt;12666.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-04&lt;/td&gt;
&lt;td&gt;18000&lt;/td&gt;
&lt;td&gt;14666.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-05&lt;/td&gt;
&lt;td&gt;21000&lt;/td&gt;
&lt;td&gt;16666.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-06&lt;/td&gt;
&lt;td&gt;19500&lt;/td&gt;
&lt;td&gt;19500.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;دو ماه اول میانگینِ ردیف‌های کمتری را می‌گیرند، چون قبل از آن‌ها چیزی نیست. قاب‌های مفیدِ دیگر &lt;code&gt;ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING&lt;/code&gt; (پنجره‌ای که ردیف فعلی وسطش است) و &lt;code&gt;ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING&lt;/code&gt; (کلِ پارتیشن) هستند.&lt;/p&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;قابِ پیش‌فرض یک غافلگیری دارد&lt;/p&gt;
&lt;p&gt;با &lt;code&gt;ORDER BY&lt;/code&gt; و بدون قاب، پیش‌فرض &lt;code&gt;RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW&lt;/code&gt; است. &lt;code&gt;RANGE&lt;/code&gt; ردیف‌هایی را که مقدارِ &lt;code&gt;ORDER BY&lt;/code&gt; &lt;strong&gt;مساوی&lt;/strong&gt; دارند یک قدم حساب می‌کند. یک جمع تجمعی روی &lt;code&gt;amount DESC&lt;/code&gt; اجرا کنید تا ببینید Ben و Cleo، که هر دو ۷۰۰ دارند، &lt;em&gt;هر دو&lt;/em&gt; ۳۵۰۰ نشان می‌دهند، چون هر کدام دیگری را هم در بر می‌گیرد. وقتی جمعِ دقیقاً ردیف‌به‌ردیف می‌خواهید، &lt;code&gt;ROWS UNBOUNDED PRECEDING&lt;/code&gt; بنویسید.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;همین پیش‌فرض یک معمای کلاسیک را توضیح می‌دهد: &lt;code&gt;LAST_VALUE(revenue) OVER (ORDER BY month)&lt;/code&gt; مقدارِ ردیفِ &lt;strong&gt;فعلی&lt;/strong&gt; را برمی‌گرداند، نه ماهِ آخر را، چون قابِ پیش‌فرض در ردیف فعلی تمام می‌شود. با &lt;code&gt;ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING&lt;/code&gt; کلِ پارتیشن را به آن بدهید.&lt;/p&gt;
&lt;h2 id=&#34;پنجره-روی-نتایج-گروهبندیشده&#34;&gt;پنجره روی نتایجِ گروه‌بندی‌شده&lt;/h2&gt;
&lt;p&gt;توابع پنجره‌ای بعد از &lt;code&gt;GROUP BY&lt;/code&gt; اجرا می‌شوند، پس می‌توانند روی خودِ گروه‌ها کار کنند. اینجا سهمِ هر منطقه از کلِ فروش را حساب می‌کنیم: &lt;code&gt;SUM(amount)&lt;/code&gt; داخلی مجموعِ منطقه است و &lt;code&gt;SUM(...) OVER ()&lt;/code&gt; بیرونی این مجموع‌ها را روی همهٔ منطقه‌ها جمع می‌زند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SUM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ROUND&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SUM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SUM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SUM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OVER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pct_of_all&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sales&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;GROUP&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;region&lt;/th&gt;
&lt;th&gt;total&lt;/th&gt;
&lt;th&gt;pct_of_all&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;North&lt;/td&gt;
&lt;td&gt;2700&lt;/td&gt;
&lt;td&gt;55.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;South&lt;/td&gt;
&lt;td&gt;2150&lt;/td&gt;
&lt;td&gt;44.3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;پنجره‌ای را که چند بار استفاده می‌کنید نام‌گذاری کنید&lt;/p&gt;
&lt;p&gt;اگر چند ستون پنجرهٔ یکسانی دارند، آن را یک بار با بخشِ &lt;code&gt;WINDOW&lt;/code&gt; بعد از &lt;code&gt;WHERE&lt;/code&gt;/&lt;code&gt;GROUP BY&lt;/code&gt;/&lt;code&gt;HAVING&lt;/code&gt; تعریف کنید: &lt;code&gt;SELECT ..., FIRST_VALUE(revenue) OVER w, LAG(revenue) OVER w FROM monthly WINDOW w AS (ORDER BY month);&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;برگه-تقلب&#34;&gt;برگهٔ تقلب&lt;/h2&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;چه می‌خواهید&lt;/th&gt;
&lt;th&gt;از چه استفاده کنید&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;مجموعِ گروه کنار هر ردیف&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SUM(x) OVER (PARTITION BY g)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;شمارهٔ ردیفِ یکتا در هر گروه&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ROW_NUMBER() OVER (PARTITION BY g ORDER BY x)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;رتبه‌بندی با در نظر گرفتن تساوی&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RANK()&lt;/code&gt; یا &lt;code&gt;DENSE_RANK()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;جمع تجمعی&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SUM(x) OVER (ORDER BY t ROWS UNBOUNDED PRECEDING)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;مقدارِ ردیفِ قبلی / بعدی&lt;/td&gt;
&lt;td&gt;&lt;code&gt;LAG(x)&lt;/code&gt; / &lt;code&gt;LEAD(x)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;میانگین متحرک&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AVG(x) OVER (ORDER BY t ROWS BETWEEN n PRECEDING AND CURRENT ROW)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;N تای برتر در هر گروه&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ROW_NUMBER()&lt;/code&gt; در یک CTE، بعد &lt;code&gt;WHERE pos &amp;lt;= N&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;تابع پنجره‌ای یک تابعِ معمولی است که بعد از آن &lt;strong&gt;&lt;code&gt;OVER (...)&lt;/code&gt;&lt;/strong&gt; می‌آید. روی ردیف‌های مرتبط محاسبه می‌کند اما &lt;strong&gt;همهٔ ردیف‌ها را نگه می‌دارد&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;PARTITION BY&lt;/code&gt;&lt;/strong&gt; ردیف‌ها را گروه‌بندی می‌کند، &lt;strong&gt;&lt;code&gt;ORDER BY&lt;/code&gt;&lt;/strong&gt; آن‌ها را داخل هر گروه مرتب می‌کند و &lt;strong&gt;قاب&lt;/strong&gt; (&lt;code&gt;ROWS BETWEEN ...&lt;/code&gt;) ردیف‌هایی را که در هر محاسبه به کار می‌روند انتخاب می‌کند.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ROW_NUMBER&lt;/code&gt;، &lt;code&gt;RANK&lt;/code&gt; و &lt;code&gt;DENSE_RANK&lt;/code&gt; فقط در رفتار با &lt;strong&gt;تساوی‌ها&lt;/strong&gt; فرق دارند.&lt;/li&gt;
&lt;li&gt;توابع پنجره‌ای &lt;strong&gt;بعد از &lt;code&gt;WHERE&lt;/code&gt; و &lt;code&gt;GROUP BY&lt;/code&gt;&lt;/strong&gt; اجرا می‌شوند؛ پس فیلتر روی آن‌ها را در یک CTE یا زیرکوئری انجام دهید.&lt;/li&gt;
&lt;li&gt;حواستان به &lt;strong&gt;قابِ پیش‌فرض&lt;/strong&gt; باشد: برای جمع تجمعیِ دقیق از &lt;code&gt;ROWS&lt;/code&gt; استفاده کنید و کلِ پارتیشن را به &lt;code&gt;LAST_VALUE&lt;/code&gt; بدهید.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;وقتی کوئری‌هایتان میلیون‌ها ردیف را خلاصه می‌کنند، سرعت مهم می‌شود؛ &lt;a href=&#34;/posts/sql-indexes-query-plans/&#34;&gt;ایندکس‌ها و پلن کوئری در SQL&lt;/a&gt; قدم طبیعیِ بعدی است.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>ایندکس‌ها و پلن کوئری در SQL: سریع کردن کوئری‌های کُند</title>
      <link>https://cryo-networks.com/posts/sql-indexes-query-plans/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/sql-indexes-query-plans/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>SQL</category>
      <description>یاد بگیرید ایندکس‌های B-tree واقعاً چطور کار می‌کنند، پلن کوئری را با EXPLAIN بخوانید، ترتیب درست ستون‌ها را در ایندکس‌های ترکیبی انتخاب کنید و اشتباه‌هایی را بشناسید که بی‌صدا یک ایندکس را از کار می‌اندازند.</description>
      <content:encoded>&lt;p&gt;کوئری‌ای که روی لپ‌تاپ شما در یک چشم به هم زدن جواب می‌دهد، ممکن است روی سرور اصلی چند ثانیه طول بکشد. معمولاً خودِ کوئری ایرادی ندارد: فقط جدول از هزار ردیف به چند میلیون ردیف رسیده و پایگاه داده برای پیدا کردن همان چند ردیفی که خواسته‌اید، &lt;strong&gt;تک‌تکِ&lt;/strong&gt; ردیف‌ها را می‌خواند.&lt;/p&gt;
&lt;p&gt;ایندکس‌ها این مشکل را حل می‌کنند؛ اما فقط ایندکسِ &lt;em&gt;درست&lt;/em&gt;، و فقط اگر کوئری شما اجازه بدهد پایگاه داده از آن استفاده کند. در این مقاله یک جدول یک‌میلیون‌ردیفی می‌سازید، می‌بینید یک کوئری از ۱۰۰ میلی‌ثانیه به کمتر از یک میلی‌ثانیه می‌رسد، و یاد می‌گیرید پلن کوئری را بخوانید تا بفهمید &lt;em&gt;چرا&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;از SQLite استفاده می‌کنیم، چون تقریباً همه‌جا نصب است و سرور نمی‌خواهد. همین ایده‌ها مستقیم در PostgreSQL و MySQL هم صدق می‌کنند؛ آخر مقاله جدولی برای تطبیق اصطلاحات آمده است. اگر JOINها هنوز برایتان تازه‌اند، از &lt;a href=&#34;/posts/sql-joins-explained/&#34;&gt;JOINها در SQL با مثال‌های ساده&lt;/a&gt; شروع کنید.&lt;/p&gt;
&lt;h2 id=&#34;ساختن-یک-میلیون-ردیف&#34;&gt;ساختن یک میلیون ردیف&lt;/h2&gt;
&lt;p&gt;یک پایگاه دادهٔ تازه با &lt;code&gt;sqlite3 shop.db&lt;/code&gt; باز کنید و این را در آن بچسبانید. این کد جدول &lt;code&gt;orders&lt;/code&gt; را می‌سازد و آن را با یک میلیون سفارش تصادفی از ۵۰ هزار مشتری پر می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;INTEGER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;PRIMARY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;INTEGER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NOT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;TEXT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NOT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;REAL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NOT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;TEXT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NOT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;WITH&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;RECURSIVE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;UNION&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ALL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1000000&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;INSERT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INTO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;abs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;random&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;50000&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CASE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;abs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;random&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHEN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;THEN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;pending&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHEN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;THEN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;cancelled&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ELSE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;shipped&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;END&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;abs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;random&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;50000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2024-01-01&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;+&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;abs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;random&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;86400000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39; seconds&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;بعد با &lt;code&gt;.timer on&lt;/code&gt; زمان‌سنجی را روشن کنید. از این به بعد هر کوئری گزارش می‌دهد چقدر طول کشیده است.&lt;/p&gt;
&lt;h2 id=&#34;خواندن-پلن-کوئری&#34;&gt;خواندن پلن کوئری&lt;/h2&gt;
&lt;p&gt;اگر قبل از هر کوئری &lt;code&gt;EXPLAIN QUERY PLAN&lt;/code&gt; بنویسید، SQLite به‌جای اجرای آن، راهبردش را نشان می‌دهد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;EXPLAIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QUERY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PLAN&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4242&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;QUERY PLAN
`--SCAN orders&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SCAN&lt;/code&gt;&lt;/strong&gt; یعنی پیمایش کامل جدول: SQLite هر یک میلیون ردیف را می‌خواند و تک‌تک بررسی می‌کند. خودِ کوئری را اجرا کنید؛ در آزمایش ما حدود &lt;strong&gt;۱۰۰ میلی‌ثانیه&lt;/strong&gt; طول کشید تا چند ردیف انگشت‌شمار را برگرداند. شاید زیاد به نظر نرسد، تا وقتی که یک صفحه آن را بیست بار اجرا کند، یا هزار کاربر هم‌زمان آن صفحه را باز کنند.&lt;/p&gt;
&lt;h2 id=&#34;ایندکس-b-tree-چطور-کار-میکند&#34;&gt;ایندکس B-tree چطور کار می‌کند&lt;/h2&gt;
&lt;p&gt;ایندکس یک نسخهٔ جداگانه و &lt;strong&gt;مرتب‌شده&lt;/strong&gt; از یک یا چند ستون است که هر ورودی‌اش به ردیف اصلی اشاره می‌کند. پایگاه‌های داده آن را به شکل یک &lt;strong&gt;B-tree&lt;/strong&gt; نگه می‌دارند: درختی کم‌عمق از صفحه‌ها (page) که هر کدام صدها کلید مرتب را در خود دارند. برای پیدا کردن &lt;code&gt;4242&lt;/code&gt;، پایگاه داده صفحهٔ ریشه را می‌خواند، اشاره‌گرِ بازه‌ای را که 4242 در آن است دنبال می‌کند و همین را تکرار می‌کند تا به یک صفحهٔ برگ برسد. چون هر صفحه به صدها فرزند منشعب می‌شود، یک میلیون ردیف فقط سه یا چهار سطح لازم دارد.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;جست‌وجوی customer_id برابر 4242 در B-tree یک صفحهٔ ریشه، یک صفحهٔ میانی و یک صفحهٔ برگ را می‌خواند و بعد فقط ردیف‌های منطبق را برمی‌دارد&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;یک ایندکس بسازید و دوباره به پلن نگاه کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INDEX&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idx_orders_customer&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;EXPLAIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QUERY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PLAN&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4242&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;QUERY PLAN
`--SEARCH orders USING INDEX idx_orders_customer (customer_id=?)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SEARCH ... USING INDEX&lt;/code&gt;&lt;/strong&gt; یعنی SQLite در ایندکس تا ورودی‌های منطبق پیش می‌رود و بعد فقط همان ردیف‌ها را از جدول برمی‌دارد. حالا همان کوئری در &lt;strong&gt;کمتر از یک میلی‌ثانیه&lt;/strong&gt; اجرا می‌شود، یعنی تقریباً صد برابر سریع‌تر؛ و این فاصله با بزرگ‌تر شدن جدول بیشتر هم می‌شود: هزینهٔ پیمایش کامل با دو برابر شدن جدول دو برابر می‌شود، اما جست‌وجو در ایندکس تقریباً تغییری حس نمی‌کند.&lt;/p&gt;
&lt;h2 id=&#34;ایندکسهای-ترکیبی-ترتیب-ستونها-همهچیز-است&#34;&gt;ایندکس‌های ترکیبی: ترتیب ستون‌ها همه‌چیز است&lt;/h2&gt;
&lt;p&gt;کوئری‌های واقعی روی بیش از یک ستون فیلتر می‌کنند. این یک نمونهٔ رایج است: سفارش‌های اخیر یک مشتری، به ترتیب تاریخ.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4242&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AND&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2025-01-01&amp;#39;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;اگر فقط &lt;code&gt;idx_orders_customer&lt;/code&gt; وجود داشته باشد، پلن یک خط دوم هم دارد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;QUERY PLAN
|--SEARCH orders USING INDEX idx_orders_customer (customer_id=?)
`--USE TEMP B-TREE FOR ORDER BY&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;USE TEMP B-TREE FOR ORDER BY&lt;/code&gt;&lt;/strong&gt; یعنی ردیف‌ها نامرتب برمی‌گردند و SQLite باید خودش آن‌ها را مرتب کند. یک &lt;strong&gt;ایندکس ترکیبی&lt;/strong&gt; روی هر دو ستون، فیلتر &lt;em&gt;و&lt;/em&gt; مرتب‌سازی را با هم حل می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INDEX&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idx_orders_customer_created&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;QUERY PLAN
`--SEARCH orders USING INDEX idx_orders_customer_created (customer_id=? AND created_at&amp;gt;?)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;ایندکس ترکیبی را مثل دفترچهٔ تلفنی تصور کنید که اول بر اساس نام خانوادگی و بعد بر اساس نام مرتب شده است. داخل بخش «4242»، ورودی‌ها از قبل بر اساس &lt;code&gt;created_at&lt;/code&gt; مرتب‌اند؛ پس پایگاه داده مستقیم به اولین تاریخی که لازم دارد می‌پرد و از آنجا جلو می‌رود. بدون هیچ مرحلهٔ مرتب‌سازی.&lt;/p&gt;
&lt;p&gt;حالا ستون‌ها را برعکس امتحان کنید. اول دو ایندکسِ مشتری را حذف کنید تا SQLite نتواند آن‌ها را انتخاب کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;DROP&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INDEX&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idx_orders_customer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;DROP&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INDEX&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idx_orders_customer_created&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INDEX&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idx_orders_created_customer&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;QUERY PLAN
`--SEARCH orders USING INDEX idx_orders_created_customer (created_at&amp;gt;?)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;هنوز &lt;code&gt;SEARCH&lt;/code&gt; نوشته، پس به نظر درست می‌آید. اما در آزمایش ما &lt;strong&gt;۹۵ میلی‌ثانیه&lt;/strong&gt; طول کشید؛ تقریباً به کندیِ حالتی که اصلاً ایندکس نداشتیم. داخل پرانتز را نگاه کنید: فقط &lt;code&gt;created_at&amp;gt;?&lt;/code&gt; از ایندکس استفاده می‌کند. این بازه حدود دو سوم همهٔ سفارش‌ها را می‌پوشاند و SQLite باید تک‌تک آن ورودی‌ها را برای &lt;code&gt;customer_id = 4242&lt;/code&gt; بررسی کند. قبل از ادامه، این ایندکس را حذف کنید (&lt;code&gt;DROP INDEX idx_orders_created_customer;&lt;/code&gt;).&lt;/p&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;قانون ترتیب ستون‌ها&lt;/p&gt;
&lt;p&gt;اول ستون‌هایی را بگذارید که با &lt;strong&gt;&lt;code&gt;=&lt;/code&gt;&lt;/strong&gt; مقایسه می‌شوند، و در آخر &lt;strong&gt;یک&lt;/strong&gt; ستون برای بازه (&lt;code&gt;&amp;gt;&lt;/code&gt;، &lt;code&gt;&amp;lt;&lt;/code&gt;، &lt;code&gt;BETWEEN&lt;/code&gt;) یا برای &lt;code&gt;ORDER BY&lt;/code&gt;. ایندکسی روی &lt;code&gt;(a, b, c)&lt;/code&gt; به کوئری‌هایی روی &lt;code&gt;a&lt;/code&gt; به‌تنهایی یا روی &lt;code&gt;a&lt;/code&gt; و &lt;code&gt;b&lt;/code&gt; هم کمک می‌کند، اما به کوئری‌هایی که فقط روی &lt;code&gt;b&lt;/code&gt; یا فقط روی &lt;code&gt;c&lt;/code&gt; هستند &lt;strong&gt;نه&lt;/strong&gt;. به این قانون &lt;em&gt;پیشوند سمت چپ&lt;/em&gt; (leftmost prefix) می‌گویند.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;SEARCH به معنی سریع نیست&lt;/p&gt;
&lt;p&gt;همیشه ببینید &lt;em&gt;کدام&lt;/em&gt; ستون‌ها داخل پرانتز آمده‌اند. یک &lt;code&gt;SEARCH&lt;/code&gt; که فقط از یک بازهٔ گسترده استفاده می‌کند، می‌تواند تقریباً به کندیِ یک &lt;code&gt;SCAN&lt;/code&gt; باشد.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;ایندکسهای-پوشا-اصلا-سراغ-جدول-نروید&#34;&gt;ایندکس‌های پوشا: اصلاً سراغ جدول نروید&lt;/h2&gt;
&lt;p&gt;حتی با یک ایندکس عالی، هر ردیف منطبق یک پرشِ اضافه از ایندکس به جدول لازم دارد تا بقیهٔ ستون‌ها خوانده شود. اگر ایندکس از قبل &lt;strong&gt;همهٔ ستون‌هایی که کوئری لازم دارد&lt;/strong&gt; را داشته باشد، پایگاه داده می‌تواند کلاً از جدول بگذرد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INDEX&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idx_orders_customer_created_total&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;EXPLAIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QUERY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PLAN&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4242&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;QUERY PLAN
`--SEARCH orders USING COVERING INDEX idx_orders_customer_created_total (customer_id=?)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;COVERING INDEX&lt;/code&gt;&lt;/strong&gt; (ایندکس پوشا) بهترین پلنی است که برای یک جست‌وجو می‌توانید بگیرید. بیشترین اثرش روی کوئری‌هایی است که ردیف‌های زیادی برمی‌گردانند، مثل گزارش‌ها و داشبوردها. این هم یک دلیل خوب دیگر برای پرهیز از &lt;code&gt;SELECT *&lt;/code&gt; است: وقتی ستون‌های کمتری بخواهید، ایندکس پوشا ممکن می‌شود.&lt;/p&gt;
&lt;h2 id=&#34;اشتباههایی-که-بیصدا-ایندکس-را-از-کار-میاندازند&#34;&gt;اشتباه‌هایی که بی‌صدا ایندکس را از کار می‌اندازند&lt;/h2&gt;
&lt;p&gt;ایندکس فقط وقتی کمک می‌کند که پایگاه داده بتواند شرط شما را مستقیم با مقدارهای مرتب‌شده مقایسه کند. اگر ستون را داخل یک تابع یا عبارت بگذارید، دیگر نمی‌تواند. فرض کنید یک ایندکس ساده روی &lt;code&gt;created_at&lt;/code&gt; اضافه کرده‌ایم و سفارش‌های یک روز را می‌خواهیم:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INDEX&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idx_orders_created&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;-- ✗ a full SCAN: date() has to be computed for every one of the million entries (≈600 ms)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;date&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2025-03-14&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;-- ✓ a SEARCH on idx_orders_created (created_at&amp;gt;? AND created_at&amp;lt;?) (&amp;lt;1 ms)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2025-03-14&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AND&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2025-03-15&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;هر دو همان تعداد را برمی‌گردانند. به شکل دوم &lt;strong&gt;sargable&lt;/strong&gt; می‌گویند (از &lt;em&gt;Search ARGument ABLE&lt;/em&gt;): ستون به‌تنهایی در یک طرف مقایسه آمده است. چند قاتل رایج دیگرِ ایندکس:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;به‌جای…&lt;/th&gt;
&lt;th&gt;بنویسید…&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WHERE date(created_at) = &#39;2025-03-14&#39;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WHERE created_at &amp;gt;= &#39;2025-03-14&#39; AND created_at &amp;lt; &#39;2025-03-15&#39;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WHERE price * 1.2 &amp;gt; 100&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WHERE price &amp;gt; 100 / 1.2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WHERE lower(email) = &#39;ada@example.com&#39;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ایمیل‌ها را با حروف کوچک ذخیره کنید، یا روی خودِ عبارت ایندکس بسازید (پایین‌تر)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WHERE name LIKE &#39;%son&#39;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;وایلدکارتِ ابتدای الگو نمی‌تواند از B-tree استفاده کند؛ جست‌وجوی تمام‌متن را در نظر بگیرید&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;وقتی واقعاً باید روی یک عبارت فیلتر کنید، روی خودِ همان عبارت ایندکس بسازید. SQLite، PostgreSQL و MySQL (از نسخهٔ ۸) همه از این پشتیبانی می‌کنند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INDEX&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idx_orders_day&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;date&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;-- now WHERE date(created_at) = &amp;#39;2025-03-14&amp;#39; uses: SEARCH orders USING INDEX idx_orders_day (&amp;lt;expr&amp;gt;=?)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;ایندکسهای-جزئی-فقط-ردیفهایی-را-ایندکس-کنید-که-کوئری-میگیرید&#34;&gt;ایندکس‌های جزئی: فقط ردیف‌هایی را ایندکس کنید که کوئری می‌گیرید&lt;/h2&gt;
&lt;p&gt;فرض کنید یک کار پس‌زمینه مدام سفارش‌های در انتظار (pending) را می‌خواهد که فقط ۱۰ درصد جدول‌اند. یک &lt;strong&gt;ایندکس جزئی&lt;/strong&gt; (partial index) فقط همین ردیف‌ها را در خود دارد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INDEX&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idx_orders_pending&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;pending&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;EXPLAIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QUERY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PLAN&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;pending&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AND&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;created_at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2024-02-01&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;QUERY PLAN
`--SEARCH orders USING INDEX idx_orders_pending (created_at&amp;lt;?)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;در پایگاه دادهٔ ما این ایندکس &lt;strong&gt;۲٫۷ مگابایت&lt;/strong&gt; جا می‌گیرد، در برابر &lt;strong&gt;۲۷ مگابایت&lt;/strong&gt; برای یک ایندکس کامل روی &lt;code&gt;created_at&lt;/code&gt;. ایندکس‌های کوچک‌تر سریع‌تر جست‌وجو می‌شوند، راحت‌تر در حافظه جا می‌گیرند و به‌روزرسانی‌شان ارزان‌تر است. PostgreSQL هم ایندکس جزئی دارد؛ MySQL ندارد.&lt;/p&gt;
&lt;h2 id=&#34;ایندکسها-رایگان-نیستند&#34;&gt;ایندکس‌ها رایگان نیستند&lt;/h2&gt;
&lt;p&gt;هر ایندکس یک ساختار دادهٔ دوم است که پایگاه داده باید مرتب نگهش دارد. هر &lt;code&gt;INSERT&lt;/code&gt;، هر &lt;code&gt;UPDATE&lt;/code&gt; روی یک ستونِ ایندکس‌شده و هر &lt;code&gt;DELETE&lt;/code&gt; باید همهٔ ایندکس‌های جدول را به‌روز کند. در آزمایش ما، درج ۲۰۰ هزار ردیفِ دیگر در جدول یک‌میلیونی بدون ایندکس ثانویه حدود &lt;strong&gt;نیم ثانیه&lt;/strong&gt; و با سه ایندکس ثانویه بیش از &lt;strong&gt;هفت ثانیه&lt;/strong&gt; طول کشید.&lt;/p&gt;
&lt;p&gt;پس هر ستونی را «محض احتیاط» ایندکس نکنید:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ستون‌هایی را ایندکس کنید که در &lt;code&gt;WHERE&lt;/code&gt;، &lt;code&gt;JOIN&lt;/code&gt; و &lt;code&gt;ORDER BY&lt;/code&gt;ِ کوئری‌های پرتکرار می‌آیند.&lt;/li&gt;
&lt;li&gt;یک ایندکس ترکیبیِ خوب‌طراحی‌شده را به چند ایندکس تک‌ستونی ترجیح دهید.&lt;/li&gt;
&lt;li&gt;دنبال ایندکس‌های تکراری بگردید: وقتی &lt;code&gt;(customer_id, created_at)&lt;/code&gt; وجود دارد، &lt;code&gt;(customer_id)&lt;/code&gt; به خاطر قانون پیشوند سمت چپ زائد است.&lt;/li&gt;
&lt;li&gt;ستون‌هایی که فقط چند مقدار متمایز دارند (مثل &lt;code&gt;status&lt;/code&gt;) به‌تنهایی به‌ندرت ایندکس خوبی می‌شوند. از آن‌ها در یک ایندکس جزئی یا به‌عنوان ستون‌های بعدیِ یک ایندکس ترکیبی استفاده کنید.&lt;/li&gt;
&lt;li&gt;بعد از تغییرات بزرگ در داده‌ها &lt;code&gt;ANALYZE&lt;/code&gt; را اجرا کنید تا برنامه‌ریز کوئری آمار به‌روز برای انتخاب بین ایندکس‌ها داشته باشد.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;خواندن-پلن-در-postgresql-و-mysql&#34;&gt;خواندن پلن در PostgreSQL و MySQL&lt;/h2&gt;
&lt;p&gt;واژه‌ها فرق می‌کنند، اما سؤال‌ها همان‌اند: &lt;em&gt;پیمایش کامل است یا جست‌وجو، از کدام ایندکس استفاده می‌شود و آیا مرحلهٔ مرتب‌سازیِ اضافه‌ای هست؟&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;چه اتفاقی می‌افتد&lt;/th&gt;
&lt;th&gt;SQLite&lt;/th&gt;
&lt;th&gt;&lt;code&gt;EXPLAIN&lt;/code&gt; در PostgreSQL&lt;/th&gt;
&lt;th&gt;&lt;code&gt;EXPLAIN&lt;/code&gt; در MySQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;کل جدول را می‌خواند&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SCAN orders&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Seq Scan on orders&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;type: ALL&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;از ایندکس استفاده می‌کند و بعد ردیف‌ها را برمی‌دارد&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SEARCH ... USING INDEX&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Index Scan&lt;/code&gt; / &lt;code&gt;Bitmap Heap Scan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;type: ref&lt;/code&gt; یا &lt;code&gt;range&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;فقط با خودِ ایندکس جواب می‌دهد&lt;/td&gt;
&lt;td&gt;&lt;code&gt;USING COVERING INDEX&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Index Only Scan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Extra: Using index&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;مرحلهٔ مرتب‌سازیِ اضافه&lt;/td&gt;
&lt;td&gt;&lt;code&gt;USE TEMP B-TREE FOR ORDER BY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Sort&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Extra: Using filesort&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;در PostgreSQL از &lt;strong&gt;&lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt;&lt;/strong&gt; استفاده کنید تا کوئری واقعاً اجرا شود و تعداد واقعیِ ردیف‌ها و زمان‌ها را کنار تخمین‌های برنامه‌ریز ببینید. وقتی تخمینی با تعداد واقعی فاصلهٔ زیادی دارد، معمولاً مقصر آمارِ قدیمی است.&lt;/p&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;SCAN&lt;/code&gt;&lt;/strong&gt; همهٔ ردیف‌ها را می‌خواند؛ &lt;strong&gt;&lt;code&gt;SEARCH ... USING INDEX&lt;/code&gt;&lt;/strong&gt; از طریق یک B-tree مرتب مستقیم سراغ ردیف‌های منطبق می‌رود.&lt;/li&gt;
&lt;li&gt;در ایندکس‌های ترکیبی &lt;strong&gt;ستون‌های تساوی را اول&lt;/strong&gt; بگذارید و بعد یک ستون برای بازه یا مرتب‌سازی. ایندکس‌ها فقط به &lt;strong&gt;پیشوند سمت چپ&lt;/strong&gt; خودشان کمک می‌کنند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ایندکس پوشا&lt;/strong&gt; بدون دست زدن به جدول به کوئری جواب می‌دهد.&lt;/li&gt;
&lt;li&gt;توابع و محاسبات روی ستونِ ایندکس‌شده &lt;strong&gt;ایندکس را از کار می‌اندازند&lt;/strong&gt;. شرط را بازنویسی کنید یا روی عبارت ایندکس بسازید.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ایندکس‌های جزئی&lt;/strong&gt; وقتی فقط زیرمجموعه‌ای از ردیف‌ها را کوئری می‌گیرید، ایندکس را کوچک نگه می‌دارند.&lt;/li&gt;
&lt;li&gt;هر ایندکس نوشتن را کُندتر می‌کند. برای کوئری‌های واقعی ایندکس بسازید و پلن را قبل و بعد از آن بررسی کنید.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;مهم‌ترین عادت: قبل از اضافه کردن ایندکس &lt;code&gt;EXPLAIN&lt;/code&gt; بگیرید، و بعد از اضافه کردنش دوباره &lt;code&gt;EXPLAIN&lt;/code&gt; بگیرید.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>الگوریتم دایکسترا: کوتاه‌ترین مسیرها با صف اولویت</title>
      <link>https://cryo-networks.com/posts/dijkstra-shortest-paths/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/dijkstra-shortest-paths/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>الگوریتم‌ها</category>
      <description>الگوریتم کوتاه‌ترین مسیرِ دایکسترا را در پایتون با heapq پیاده کنید، قدم‌به‌قدم دنبالش کنید، بفهمید چرا درست است و دقیقاً یاد بگیرید کِی خراب می‌شود: یال‌های منفی، تساوی در هیپ و گراف‌های چگال.</description>
      <content:encoded>&lt;p&gt;اپ نقشه‌تان که مسیری پیدا می‌کند، روتری که تصمیم می‌گیرد یک بسته را به کجا بفرستد، شخصیتی در یک بازی که دور موانع راه می‌رود: همه نسخه‌هایی از یک سؤال‌اند. &lt;em&gt;در گرافی که یال‌هایش وزن دارند، ارزان‌ترین مسیر از اینجا به هر جای دیگر کدام است؟&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;برای گراف‌های بدون وزن، جست‌وجوی سطح‌اول (BFS) جواب می‌دهد: اول یک قدم دورتر را بگرد، بعد دو قدم، بعد سه قدم. وزن‌ها این را خراب می‌کنند. مسیری با سه یالِ ارزان می‌تواند از مسیری با یک یالِ گران بهتر باشد؛ پس «کمترین تعداد قدم» دیگر یعنی «کوتاه‌ترین» نیست. &lt;strong&gt;الگوریتم دایکسترا&lt;/strong&gt; (Dijkstra) که ادسخر دایکسترا در سال ۱۹۵۹ منتشرش کرد، این مشکل را با یک قاعده حل می‌کند: همیشه &lt;strong&gt;نزدیک‌ترین گرهِ تمام‌نشده&lt;/strong&gt; را بعد از همه گسترش بده.&lt;/p&gt;
&lt;p&gt;این مقاله الگوریتم را در پایتون می‌سازد، آن را روی یک گراف واقعی دنبال می‌کند، توضیح می‌دهد چرا کار می‌کند و به جزئیاتی می‌پردازد که نسخهٔ کتاب درسی را از نسخه‌ای که می‌شود به آن اعتماد کرد جدا می‌کند: ورودی‌های کهنه در هیپ، تساوی‌ها، وزن‌های منفی و پیچیدگی. باید با Big-O (&lt;a href=&#34;/posts/big-o-notation-explained/&#34;&gt;نماد Big-O با کد واقعی&lt;/a&gt;) و دیکشنری‌های پایتون راحت باشید.&lt;/p&gt;
&lt;h2 id=&#34;گراف-نمونه&#34;&gt;گراف نمونه&lt;/h2&gt;
&lt;p&gt;شش مکان که با جاده به هم وصل‌اند و روی هر جاده زمانِ سفر نوشته شده. جاده‌ها دوطرفه‌اند.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;گرافی با شش گره. کوتاه‌ترین فاصله‌ها از A: A برابر ۰، C برابر ۲، B برابر ۳، D برابر ۸، E برابر ۱۰ و F برابر ۱۲. درخت کوتاه‌ترین مسیرِ برجسته از یال‌های A–C، C–B، B–D، D–E و E–F تشکیل شده&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;گراف را به شکل یک &lt;strong&gt;نقشهٔ مجاورت&lt;/strong&gt; (adjacency map) نگه می‌داریم: برای هر گره، دیکشنری‌ای از همسایه‌ها و وزنِ یال‌ها.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;collections&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;defaultdict&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;edges&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;D&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;D&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
         &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;E&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;D&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;E&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;D&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;F&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;E&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;F&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;graph&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;defaultdict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;w&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;edges&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;graph&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;w&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;graph&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;w&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;# undirected: add both directions&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;ایده&#34;&gt;ایده&lt;/h2&gt;
&lt;p&gt;برای هر گره یک فاصلهٔ موقت نگه دارید: ۰ برای مبدأ و بی‌نهایت برای بقیه. بعد این را تکرار کنید:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;گرهِ تمام‌نشده‌ای را که &lt;strong&gt;کمترین&lt;/strong&gt; فاصلهٔ موقت را دارد انتخاب کنید. فاصلهٔ آن حالا نهایی است.&lt;/li&gt;
&lt;li&gt;همهٔ یال‌هایش را &lt;strong&gt;آزادسازی&lt;/strong&gt; (relax) کنید: اگر عبور از این گره فاصلهٔ کوتاه‌تری از فاصلهٔ فعلیِ یک همسایه به او می‌دهد، همسایه را به‌روز کنید.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;تنها بخشِ سخت مرحلهٔ ۱ است: پیدا کردنِ سریعِ کمترین فاصله. پیمایشِ همهٔ گره‌ها در هر مرحله O(V) هزینه دارد. یک &lt;strong&gt;صف اولویت&lt;/strong&gt; (یک هیپ دودویی) آن را به O(log V) می‌رساند.&lt;/p&gt;
&lt;h2 id=&#34;پیادهسازی&#34;&gt;پیاده‌سازی&lt;/h2&gt;
&lt;p&gt;ماژول &lt;code&gt;heapq&lt;/code&gt; پایتون یک لیستِ ساده را به یک min-heap تبدیل می‌کند. این ماژول عملیاتِ «کاهش کلید» (decrease key) ندارد؛ پس وقتی فاصلهٔ یک گره بهتر می‌شود، فقط یک ورودیِ &lt;strong&gt;جدید&lt;/strong&gt; push می‌کنیم و ورودیِ قدیمی را در هیپ رها می‌کنیم. وقتی ورودیِ قدیمی بالاخره بیرون می‌آید، آن را &lt;strong&gt;کهنه&lt;/strong&gt; (stale) تشخیص می‌دهیم و از آن رد می‌شویم. به این &lt;em&gt;حذف تنبل&lt;/em&gt; (lazy deletion) می‌گویند و تقریباً همهٔ پیاده‌سازی‌های پایتون همین‌طور کار می‌کنند.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;heapq&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;dijkstra&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;graph&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;dist&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;                             &lt;span class=&#34;c1&#34;&gt;# prev[node] = the node we reached it from&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;heap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;heap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;heapq&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;heappop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;heap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dist&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;                      &lt;span class=&#34;c1&#34;&gt;# stale entry: we already found a shorter way here&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;neighbor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;weight&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;graph&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;new_dist&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;weight&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;new_dist&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dist&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;neighbor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;inf&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;dist&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;neighbor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;new_dist&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;neighbor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;heapq&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;heappush&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;heap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new_dist&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;neighbor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dist&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dist&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dijkstra&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;graph&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dist&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;C&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;D&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;E&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;F&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;گره‌هایی که از مبدأ نمی‌شود به آن‌ها رسید، اصلاً در &lt;code&gt;dist&lt;/code&gt; ظاهر نمی‌شوند.&lt;/p&gt;
&lt;h2 id=&#34;بازسازی-مسیر&#34;&gt;بازسازیِ مسیر&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;dist&lt;/code&gt; طولِ هر کوتاه‌ترین مسیر را می‌دهد؛ &lt;code&gt;prev&lt;/code&gt; اجازه می‌دهد خودِ مسیر را با حرکت به عقب از مقصد بازسازی کنیم:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;path_to&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]])&lt;/span&gt;       &lt;span class=&#34;c1&#34;&gt;# KeyError means target is unreachable&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[::&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;

&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;path_to&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;F&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;C&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;D&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;E&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;F&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;اشاره‌گرهای &lt;code&gt;prev&lt;/code&gt; یک &lt;strong&gt;درخت کوتاه‌ترین مسیر&lt;/strong&gt; با ریشهٔ مبدأ می‌سازند: همان یال‌های برجسته در نمودار. دقت کنید بهترین مسیر به B جادهٔ مستقیم (۴) نیست، بلکه دور زدن از طریق C است (۲ + ۱ = ۳).&lt;/p&gt;
&lt;h2 id=&#34;دنبال-کردن-قدمبهقدم&#34;&gt;دنبال کردنِ قدم‌به‌قدم&lt;/h2&gt;
&lt;p&gt;این همهٔ عملیات‌های هیپ برای گراف ماست. به ورودی‌های &lt;strong&gt;کهنه&lt;/strong&gt; دقت کنید: B، D، E و F هر کدام دو بار push می‌شوند، چون بعد از push اول مسیرِ کوتاه‌تری پیدا شده.&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pop&lt;/th&gt;
&lt;th&gt;کار&lt;/th&gt;
&lt;th&gt;هیپ بعد از آن&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;(0, A)&lt;/td&gt;
&lt;td&gt;A نهایی؛ B = 4، C = 2&lt;/td&gt;
&lt;td&gt;(2, C) (4, B)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(2, C)&lt;/td&gt;
&lt;td&gt;C نهایی؛ B = 3، D = 10، E = 12&lt;/td&gt;
&lt;td&gt;(3, B) (4, B) (10, D) (12, E)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(3, B)&lt;/td&gt;
&lt;td&gt;B نهایی؛ D = 8&lt;/td&gt;
&lt;td&gt;(4, B) (8, D) (10, D) (12, E)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(4, B)&lt;/td&gt;
&lt;td&gt;کهنه، رد شو&lt;/td&gt;
&lt;td&gt;(8, D) (10, D) (12, E)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(8, D)&lt;/td&gt;
&lt;td&gt;D نهایی؛ E = 10، F = 14&lt;/td&gt;
&lt;td&gt;(10, D) (10, E) (12, E) (14, F)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(10, D)&lt;/td&gt;
&lt;td&gt;کهنه، رد شو&lt;/td&gt;
&lt;td&gt;(10, E) (12, E) (14, F)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(10, E)&lt;/td&gt;
&lt;td&gt;E نهایی؛ F = 12&lt;/td&gt;
&lt;td&gt;(12, E) (12, F) (14, F)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(12, E)&lt;/td&gt;
&lt;td&gt;کهنه، رد شو&lt;/td&gt;
&lt;td&gt;(12, F) (14, F)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(12, F)&lt;/td&gt;
&lt;td&gt;F نهایی&lt;/td&gt;
&lt;td&gt;(14, F)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(14, F)&lt;/td&gt;
&lt;td&gt;کهنه، رد شو&lt;/td&gt;
&lt;td&gt;خالی&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;چرا-درست-است&#34;&gt;چرا درست است&lt;/h2&gt;
&lt;p&gt;ادعای اصلی این است: &lt;strong&gt;وقتی گره‌ای با فاصلهٔ فعلی‌اش &lt;code&gt;d&lt;/code&gt; از هیپ بیرون می‌آید، هیچ مسیرِ کوتاه‌تری به آن وجود ندارد.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;فرض کنید مسیرِ کوتاه‌تری وجود داشت. این مسیر از مبدأ (که از قبل نهایی شده) شروع می‌شود و به گرهِ ما ختم می‌شود؛ پس جایی در طول آن اولین گرهی هست که هنوز نهایی نشده؛ اسمش را &lt;code&gt;u&lt;/code&gt; بگذارید. بخشی از مسیر که قبل از &lt;code&gt;u&lt;/code&gt; است از گره‌های نهایی‌شده می‌گذرد؛ پس &lt;code&gt;u&lt;/code&gt; با همان فاصله آزادسازی شده و با کلیدی در هیپ نشسته که از طولِ مسیر تا &lt;code&gt;u&lt;/code&gt; بیشتر نیست. چون همهٔ وزن‌ها &lt;strong&gt;نامنفی‌اند&lt;/strong&gt;، یال‌های باقی‌مانده فقط می‌توانند به آن اضافه کنند؛ پس کلیدِ &lt;code&gt;u&lt;/code&gt; حداکثر به اندازهٔ طولِ آن مسیرِ کوتاه‌تر است، که از &lt;code&gt;d&lt;/code&gt; کمتر است. اما در این صورت هیپ باید &lt;code&gt;u&lt;/code&gt; را قبل از گرهِ ما به ما می‌داد. تناقض.&lt;/p&gt;
&lt;p&gt;این استدلال دقیقاً به یک فرض تکیه دارد: &lt;strong&gt;وزن‌های نامنفی&lt;/strong&gt;. آن را بردارید تا کل ماجرا فرو بریزد.&lt;/p&gt;
&lt;h2 id=&#34;یالهای-منفی-خرابش-میکنند&#34;&gt;یال‌های منفی خرابش می‌کنند&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;graph&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;D&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;D&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{}}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;فاصلهٔ واقعی تا B برابر ۱ است (A → C → B) و تا D برابر ۳. اما دایکسترا B (با فاصلهٔ ۲) را قبل از C (با فاصلهٔ ۳) بیرون می‌کشد؛ پس B را تمام‌شده حساب می‌کند پیش از آنکه مسیرِ ارزان‌تر از طریق C دیده شود. نسخه‌های کتاب درسی که گره‌ها را «تمام‌شده» علامت می‌زنند B = 2 و D = 4 برمی‌گردانند، که غلط است.&lt;/p&gt;
&lt;p&gt;نسخهٔ تنبلِ ما اینجا اتفاقاً خودش را درست می‌کند، چون وقتی فاصلهٔ کوتاه‌تر پیدا می‌شود B را دوباره push می‌کند و بعد B را دوباره پردازش می‌کند. به این تکیه نکنید: با یال‌های منفی یک گره ممکن است بارها و بارها دوباره پردازش شود و روی گراف‌های بدخواهانه زمان اجرا نمایی می‌شود. اگر گرافتان ممکن است وزن منفی داشته باشد، از الگوریتم &lt;strong&gt;Bellman–Ford&lt;/strong&gt; با پیچیدگی O(V·E) استفاده کنید که دورهای منفی را هم تشخیص می‌دهد؛ جایی که اصلاً کوتاه‌ترین مسیری وجود ندارد.&lt;/p&gt;
&lt;div class=&#34;admonition note&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;تست با Bellman–Ford&lt;/p&gt;
&lt;p&gt;Bellman–Ford کوتاه و کُند است، و همین آن را به یک پیاده‌سازیِ مرجعِ عالی تبدیل می‌کند: همهٔ یال‌ها را V − 1 بار آزادسازی کنید. مقایسهٔ &lt;code&gt;dijkstra()&lt;/code&gt; با آن روی چند هزار گرافِ تصادفیِ کوچک با وزن‌های نامنفی راهی سریع برای پیدا کردنِ باگ‌های پیاده‌سازی‌تان است.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;پیچیدگی&#34;&gt;پیچیدگی&lt;/h2&gt;
&lt;p&gt;هر گره فقط یک بار پردازش می‌شود (ورودی‌های بعدی‌اش به‌عنوان کهنه رد می‌شوند)؛ پس هر یال حداکثر یک بار در هر جهت آزادسازی می‌شود و حداکثر یک push ایجاد می‌کند. در نتیجه هیپ O(E) ورودی دارد و هر push و pop هزینهٔ O(log E) دارد. چون E حداکثر V² است، log E حداکثر 2 log V است، که نتیجه می‌دهد:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;زمان: O((V + E) log V)&lt;/strong&gt; با یک هیپ دودویی.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;حافظه: O(V + E)&lt;/strong&gt; برای گراف، فاصله‌ها و هیپ.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;برای گراف‌های &lt;strong&gt;چگال&lt;/strong&gt;، که E نزدیک به V² است، یک نسخهٔ ساده‌ترِ O(V²) بدون هیپ در واقع سریع‌تر است: یک آرایه از فاصله‌ها نگه دارید و هر بار برای پیدا کردنِ کمینه آن را پیمایش کنید. ساختارهای نظری مثل هیپ فیبوناچی به O(E + V log V) می‌رسند، اما سربارشان در عمل به‌ندرت می‌ارزد.&lt;/p&gt;
&lt;h2 id=&#34;جزئیات-عملی&#34;&gt;جزئیات عملی&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;زود متوقف شوید.&lt;/strong&gt; اگر فقط مسیر به یک مقصد را لازم دارید، به محض اینکه آن را pop کردید برگردید. فاصله‌اش در همان لحظه نهایی است و روی یک گراف بزرگ می‌توانید از بیشترِ کار صرف‌نظر کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;        &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;heapq&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;heappop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;heap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;تساوی در هیپ.&lt;/strong&gt; ورودی‌های هیپ تاپل‌اند؛ پس وقتی دو فاصله برابرند پایتون خودِ گره‌ها را مقایسه می‌کند. برای رشته‌ها و عددها مشکلی نیست، اما اشیائی که از &lt;code&gt;&amp;lt;&lt;/code&gt; پشتیبانی نمی‌کنند &lt;code&gt;TypeError&lt;/code&gt; می‌دهند. یک شمارنده را به‌عنوان معیارِ دوم اضافه کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;itertools&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;count&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;tiebreak&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;heapq&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;heappush&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;heap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new_dist&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;next&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tiebreak&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;neighbor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;وزن‌های اعشاری.&lt;/strong&gt; با وزن‌های float، دو مسیرِ «هم‌طول» ممکن است به‌خاطر خطای گرد کردن کمی فرق کنند. وقتی خودِ مسیر دقیقاً مهم است، با یک حدِ تحمل مقایسه کنید یا به عددهای صحیح (سانتی‌متر، میلی‌ثانیه) تبدیل کنید.&lt;/p&gt;
&lt;h2 id=&#34;قدمهای-بعدی&#34;&gt;قدم‌های بعدی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;الگوریتم &lt;code&gt;A*&lt;/code&gt;&lt;/strong&gt; همان دایکسترا به‌علاوهٔ یک &lt;em&gt;تابع تخمین&lt;/em&gt; (heuristic) است: هیپ را بر اساس &lt;code&gt;distance + estimate_to_target&lt;/code&gt; مرتب می‌کند. با یک تخمینِ خوب (مثل فاصلهٔ خط مستقیم روی نقشه) گره‌های بسیار کمتری را می‌گردد و همچنان کوتاه‌ترین مسیر را پیدا می‌کند، به شرطی که تخمین هرگز بیشتر از مقدار واقعی نباشد.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;مسیریابیِ شبکه&lt;/strong&gt; مستقیماً از دایکسترا استفاده می‌کند: روترهای OSPF با آن کوتاه‌ترین مسیرها را روی نقشهٔ شبکه حساب می‌کنند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;شبکه‌های جاده‌ای&lt;/strong&gt; در مقیاس یک قاره از تکنیک‌های پیش‌پردازش مثل contraction hierarchies استفاده می‌کنند که در هسته‌شان جست‌وجوهایی به سبک دایکسترا هست.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;دایکسترا کوتاه‌ترین مسیرها را از یک مبدأ در گراف‌هایی با وزن یالِ &lt;strong&gt;نامنفی&lt;/strong&gt; پیدا می‌کند.&lt;/li&gt;
&lt;li&gt;همیشه &lt;strong&gt;نزدیک‌ترین گرهِ تمام‌نشده&lt;/strong&gt; را گسترش دهید؛ یک min-heap (&lt;code&gt;heapq&lt;/code&gt;) آن را در O(log V) پیدا می‌کند.&lt;/li&gt;
&lt;li&gt;بدون decrease-key، &lt;strong&gt;ورودی‌های تکراری push کنید و از ورودی‌های کهنه رد شوید&lt;/strong&gt; (&lt;code&gt;if d &amp;gt; dist[node]: continue&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;اشاره‌گرهای &lt;code&gt;prev&lt;/code&gt;&lt;/strong&gt; را برای بازسازیِ مسیرها نگه دارید؛ این‌ها یک درخت کوتاه‌ترین مسیر می‌سازند.&lt;/li&gt;
&lt;li&gt;زمان اجرا &lt;strong&gt;O((V + E) log V)&lt;/strong&gt; است؛ برای یال‌های منفی از &lt;strong&gt;Bellman–Ford&lt;/strong&gt; و برای گراف‌های خیلی چگال از پیمایشِ آرایه با O(V²) استفاده کنید.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
    </item>
    <item>
      <title>آبشار و Specificity در CSS: چرا استایل‌هایتان اعمال نمی‌شوند</title>
      <link>https://cryo-networks.com/posts/css-cascade-specificity/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/css-cascade-specificity/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>CSS</category>
      <description>وقتی دو قاعدهٔ CSS با هم مخالف‌اند، مرورگر برای انتخاب برنده از مجموعه‌ای از قواعدِ دقیق پیروی می‌کند. یاد بگیرید آبشار چطور تصمیم می‌گیرد، specificity را با دست حساب کنید و دیگر سراغ !important نروید.</description>
      <content:encoded>&lt;p&gt;یک قاعدهٔ CSS می‌نویسید. صفحه را دوباره بارگذاری می‌کنید. هیچ چیزی عوض نمی‌شود. DevTools را باز می‌کنید و آنجاست، &lt;strong&gt;خط خورده&lt;/strong&gt;: قاعدهٔ دیگری در جایی برنده شده. پس یک کلاس اضافه می‌کنید، بعد یک ID، بعد &lt;code&gt;!important&lt;/code&gt;، و شش ماه بعد هیچ‌کس جرئت نمی‌کند به استایل‌شیت دست بزند.&lt;/p&gt;
&lt;p&gt;اینکه کدام قاعده برنده می‌شود هیچ چیزِ تصادفی‌ای ندارد. وقتی چند اعلان (declaration) یک ویژگی را روی یک عنصر تنظیم می‌کنند، مرورگر &lt;strong&gt;آبشار&lt;/strong&gt; (cascade) را اجرا می‌کند: یک توالیِ ثابت از معیارهای تعیین برنده. این توالی را یاد بگیرید تا هر بار برنده را پیش‌بینی کنید و CSSی بنویسید که اصلاً به &lt;code&gt;!important&lt;/code&gt; نیاز نداشته باشد. (اگر هنوز با چیدمان راحت نیستید، &lt;a href=&#34;/posts/css-flexbox-vs-grid/&#34;&gt;Flexbox یا Grid در CSS&lt;/a&gt; شروع خوبی است.)&lt;/p&gt;
&lt;h2 id=&#34;آبشار-به-ترتیب&#34;&gt;آبشار، به ترتیب&lt;/h2&gt;
&lt;p&gt;مرورگر برای هر ویژگیِ هر عنصر، همهٔ اعلان‌هایی را که اعمال می‌شوند جمع می‌کند و بعد آن‌ها را به این ترتیب مقایسه می‌کند. &lt;strong&gt;اولین مرحله‌ای که تفاوتی پیدا کند تصمیم می‌گیرد&lt;/strong&gt;؛ مرحله‌های بعدی فقط تساوی را می‌شکنند.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;آبشار اعلان‌ها را مرحله‌به‌مرحله مقایسه می‌کند: منشأ و اهمیت، استایل درون‌خطی، لایهٔ آبشار، specificity و در آخر ترتیب ظاهر شدن؛ اولین مرحله‌ای که تفاوتی داشته باشد برنده را انتخاب می‌کند&lt;/figcaption&gt;&lt;/figure&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;منشأ و اهمیت.&lt;/strong&gt; استایل‌شیت‌های شما بر استایل‌های پیش‌فرضِ مرورگر غلبه می‌کنند. اعلانی که با &lt;code&gt;!important&lt;/code&gt; علامت خورده بر همهٔ اعلان‌های معمولی غلبه می‌کند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;استایل‌های درون‌خطی.&lt;/strong&gt; ویژگیِ &lt;code&gt;style=&#34;…&#34;&lt;/code&gt; بر هر سلکتوری در استایل‌شیت غلبه می‌کند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;لایه‌های آبشار.&lt;/strong&gt; اگر از &lt;code&gt;@layer&lt;/code&gt; استفاده کنید، استایل‌های لایه‌های بعدی بر لایه‌های قبلی غلبه می‌کنند، سلکتورهایشان هر چه باشد.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Specificity.&lt;/strong&gt; سلکتورِ دقیق‌تر برنده است.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ترتیب ظاهر شدن.&lt;/strong&gt; اگر همه‌چیزِ دیگر برابر باشد، اعلانی که &lt;strong&gt;آخر&lt;/strong&gt; می‌آید برنده است.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;بیشترِ غافلگیری‌های روزمره در مرحله‌های ۴ و ۵ اتفاق می‌افتند، پس از همان‌جا شروع کنیم.&lt;/p&gt;
&lt;h2 id=&#34;محاسبه-specificity&#34;&gt;محاسبهٔ specificity&lt;/h2&gt;
&lt;p&gt;Specificity امتیازی است که از سه عدد ساخته می‌شود و معمولاً به شکل &lt;strong&gt;(A, B, C)&lt;/strong&gt; نوشته می‌شود:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A&lt;/strong&gt;: تعداد سلکتورهای &lt;strong&gt;ID&lt;/strong&gt; (&lt;code&gt;#header&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;B&lt;/strong&gt;: تعداد سلکتورهای &lt;strong&gt;کلاس&lt;/strong&gt; (&lt;code&gt;.card&lt;/code&gt;)، سلکتورهای &lt;strong&gt;attribute&lt;/strong&gt; (&lt;code&gt;[type=&#34;email&#34;]&lt;/code&gt;) و &lt;strong&gt;شبه‌کلاس‌ها&lt;/strong&gt; (&lt;code&gt;:hover&lt;/code&gt;، &lt;code&gt;:focus&lt;/code&gt;، &lt;code&gt;:nth-child()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;C&lt;/strong&gt;: تعداد سلکتورهای &lt;strong&gt;نوع&lt;/strong&gt; (&lt;code&gt;p&lt;/code&gt;، &lt;code&gt;button&lt;/code&gt;) و &lt;strong&gt;شبه‌عنصرها&lt;/strong&gt; (&lt;code&gt;::before&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;سلکتورِ همگانیِ &lt;code&gt;*&lt;/code&gt; و ترکیب‌کننده‌ها (&lt;code&gt;&lt;/code&gt;، &lt;code&gt;&amp;gt;&lt;/code&gt;، &lt;code&gt;+&lt;/code&gt;، &lt;code&gt;~&lt;/code&gt;) هیچ امتیازی ندارند.&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;سلکتور&lt;/th&gt;
&lt;th&gt;Specificity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(0, 0, 1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.card p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(0, 1, 1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.card .title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(0, 2, 0)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a:hover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(0, 1, 1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;input[type=&#34;email&#34;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(0, 1, 1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ul li::before&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(0, 0, 3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#sidebar a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(1, 0, 1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#nav .item a:hover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(1, 2, 1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(0, 0, 0)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;برای مقایسهٔ دو سلکتور، اول &lt;strong&gt;A&lt;/strong&gt; را مقایسه کنید. فقط اگر A برابر بود سراغ B بروید، و فقط اگر B برابر بود سراغ C. بین ستون‌ها هیچ «انتقالی» وجود ندارد: یک ID یعنی (1, 0, 0) بر سلکتوری با بیست کلاس یعنی (0, 20, 0) غلبه می‌کند.&lt;/p&gt;
&lt;p&gt;این یک غافلگیریِ کلاسیک است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;gray&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* (1, 1, 0) */&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;primary&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;blue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* (0, 2, 0) */&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;button primary&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Save&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;   &lt;span class=&#34;cm&#34;&gt;&amp;lt;!-- gray! --&amp;gt;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;دکمهٔ primary خاکستری است، با اینکه &lt;code&gt;.button.primary&lt;/code&gt; از نظر یک آدم دقیق‌تر به نظر می‌رسد و بعدتر هم آمده. ID در ستون A برنده می‌شود و کار هرگز به مرحلهٔ ۵ نمی‌رسد.&lt;/p&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;بگذارید DevTools حساب کند&lt;/p&gt;
&lt;p&gt;در مرورگرهای مبتنی بر Chromium، نشانگر ماوس را روی یک سلکتور در پنل &lt;strong&gt;Styles&lt;/strong&gt; نگه دارید تا specificity آن را ببینید. زبانهٔ &lt;strong&gt;Computed&lt;/strong&gt; مقدار نهاییِ هر ویژگی را نشان می‌دهد و وقتی بازش کنید، همهٔ قاعده‌هایی را که سعی کرده‌اند آن را تنظیم کنند، با برنده در ابتدا.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;شبهکلاسهای-is-not-has-و-where&#34;&gt;شبه‌کلاس‌های :is()، :not()، :has() و :where()&lt;/h2&gt;
&lt;p&gt;این شبه‌کلاس‌ها فهرستی از سلکتورها می‌گیرند و امتیازشان طور دیگری حساب می‌شود:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:is()&lt;/code&gt;، &lt;code&gt;:not()&lt;/code&gt; و &lt;code&gt;:has()&lt;/code&gt; specificity &lt;strong&gt;دقیق‌ترین آرگومانشان&lt;/strong&gt; را می‌گیرند. &lt;code&gt;:is(#nav, .menu) a&lt;/code&gt; امتیاز (1, 0, 1) دارد، حتی وقتی از طریق &lt;code&gt;.menu&lt;/code&gt; منطبق می‌شود.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:where()&lt;/code&gt; همیشه specificity &lt;strong&gt;صفر&lt;/strong&gt; دارد، هر چه داخلش باشد.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;همین &lt;code&gt;:where()&lt;/code&gt; را برای پیش‌فرض‌هایی که باید راحت بازنویسی شوند عالی می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;c&#34;&gt;/* (0, 0, 1): any later class beats it */&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;prose&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;royalblue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;/* (0, 1, 1): would beat most component styles, which is usually not what you want */&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;prose&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;royalblue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;ارثبری-همان-آبشار-نیست&#34;&gt;ارث‌بری همان آبشار نیست&lt;/h2&gt;
&lt;p&gt;بعضی ویژگی‌ها، بیشترشان مربوط به متن مثل &lt;code&gt;color&lt;/code&gt;، &lt;code&gt;font-family&lt;/code&gt; و &lt;code&gt;line-height&lt;/code&gt;، &lt;strong&gt;به ارث می‌رسند&lt;/strong&gt;: اگر هیچ چیزی آن‌ها را روی یک عنصر تنظیم نکند، عنصر مقدارِ والدش را می‌گیرد. بقیه، مثل &lt;code&gt;margin&lt;/code&gt;، &lt;code&gt;border&lt;/code&gt; و &lt;code&gt;background&lt;/code&gt;، به ارث نمی‌رسند.&lt;/p&gt;
&lt;p&gt;تله اینجاست: &lt;strong&gt;یک مقدارِ به‌ارث‌رسیده همیشه به هر قاعده‌ای که مستقیماً خودِ عنصر را هدف می‌گیرد می‌بازد&lt;/strong&gt;، سلکتورِ آن قاعده هر قدر هم ضعیف باشد.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;article&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;darkred&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* (1, 0, 0), but applies to the div */&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;black&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* (0, 0, 1), applies to the p itself */&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;article&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;This text is black, not dark red.&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Specificity فقط قاعده‌هایی را مقایسه می‌کند که با &lt;strong&gt;یک عنصرِ واحد&lt;/strong&gt; منطبق می‌شوند. قاعدهٔ &lt;code&gt;#article&lt;/code&gt; با &lt;code&gt;div&lt;/code&gt; منطبق می‌شود؛ پاراگراف فقط از آن ارث می‌برد، و ارث‌بری فقط وقتی وارد عمل می‌شود که هیچ قاعده‌ای &lt;code&gt;color&lt;/code&gt; را روی خودِ پاراگراف تنظیم نکند.&lt;/p&gt;
&lt;p&gt;چهار کلیدواژه به شما اجازه می‌دهند این را روی هر ویژگی‌ای صریحاً کنترل کنید:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;کلیدواژه&lt;/th&gt;
&lt;th&gt;معنی&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;inherit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;مقدارِ والد را بگیر&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;initial&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;از مقدارِ پیش‌فرضِ ویژگی در مشخصات CSS استفاده کن&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;unset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;برای ویژگی‌های ارثی مثل &lt;code&gt;inherit&lt;/code&gt;، برای بقیه مثل &lt;code&gt;initial&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;revert&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;به همان چیزی برگرد که استایل‌شیتِ خودِ مرورگر تنظیم می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;کلیدواژه-important-و-استایلهای-درونخطی&#34;&gt;کلیدواژهٔ !important و استایل‌های درون‌خطی&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;!important&lt;/code&gt; در مرحلهٔ ۱ از صف جلو می‌زند، حتی قبل از اینکه به specificity نگاه شود. دقیقاً به همین دلیل دردسر می‌سازد: تنها راهِ بازنویسیِ یک اعلانِ &lt;code&gt;!important&lt;/code&gt; یک اعلانِ &lt;code&gt;!important&lt;/code&gt; دیگر است که در مرحله‌های بعدی برنده شود، و این‌طور مسابقهٔ تسلیحاتی شروع می‌شود.&lt;/p&gt;
&lt;p&gt;ویژگی‌های &lt;code&gt;style&lt;/code&gt; درون‌خطی (مرحلهٔ ۲) بر هر سلکتوری غلبه می‌کنند، اما به &lt;code&gt;!important&lt;/code&gt; در استایل‌شیت می‌بازند.&lt;/p&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;کلیدواژهٔ !important را برای کلاس‌های کمکی نگه دارید&lt;/p&gt;
&lt;p&gt;یک استفادهٔ معقول، یک کلاسِ کمکیِ کوچک است که باید همیشه برنده شود، مثل &lt;code&gt;.hidden { display: none !important; }&lt;/code&gt;. استفاده از آن برای حل یک مشکلِ specificity فقط مشکل را تا دفعهٔ بعد پنهان می‌کند.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;لایههای-آبشار-specificity-تحت-کنترل&#34;&gt;لایه‌های آبشار: specificity تحت کنترل&lt;/h2&gt;
&lt;p&gt;لایه‌های آبشار (&lt;code&gt;@layer&lt;/code&gt;، که از سال ۲۰۲۲ در همهٔ مرورگرهای اصلی پشتیبانی می‌شود) یک مرحله &lt;strong&gt;بالاتر از&lt;/strong&gt; specificity اضافه می‌کنند. ترتیب لایه‌هایتان را یک بار اعلام می‌کنید و از آن به بعد لایهٔ بعدی بر لایهٔ قبلی غلبه می‌کند، سلکتورها هر چه باشند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;layer&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;reset&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;vendor&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;components&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;utilities&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;layer&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;vendor&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;btn&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;gray&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* (1, 1, 0) */&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;layer&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;components&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;btn&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;royalblue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* (0, 1, 0), and it wins */&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;در عبارتِ &lt;code&gt;@layer&lt;/code&gt;، لایهٔ &lt;code&gt;components&lt;/code&gt; بعد از &lt;code&gt;vendor&lt;/code&gt; آمده؛ پس &lt;code&gt;.btn&lt;/code&gt; آن با وجود specificity خیلی کمتر برنده می‌شود. این برای CSS کتابخانه‌های بیرونی ایده‌آل است: آن را در یک لایهٔ اولیه بپیچید (&lt;code&gt;@import url(&#34;library.css&#34;) layer(vendor);&lt;/code&gt;) تا استایل‌های خودتان بدون ترفندهای specificity بر آن غلبه کنند.&lt;/p&gt;
&lt;p&gt;دو جزئیاتِ ارزشمند: استایل‌هایی که در هیچ لایه‌ای نیستند بر همهٔ استایل‌های لایه‌دار غلبه می‌کنند، و برای اعلان‌های &lt;code&gt;!important&lt;/code&gt; ترتیب لایه‌ها برعکس می‌شود؛ یعنی &lt;code&gt;!important&lt;/code&gt; یک لایهٔ قبلی بر &lt;code&gt;!important&lt;/code&gt; لایهٔ بعدی غلبه می‌کند.&lt;/p&gt;
&lt;h2 id=&#34;عادتهایی-که-جلوی-جنگ-specificity-را-میگیرند&#34;&gt;عادت‌هایی که جلوی جنگِ specificity را می‌گیرند&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;با کلاس استایل بدهید، نه با ID.&lt;/strong&gt; IDها را برای لینک‌های داخلی و جاوااسکریپت نگه دارید.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;سلکتورها را کوتاه و تخت نگه دارید.&lt;/strong&gt; &lt;code&gt;.card-title&lt;/code&gt; به‌جای &lt;code&gt;.sidebar .card &amp;gt; h2.title&lt;/code&gt;. سلکتورهای تخت specificity مشابهی دارند، پس ترتیبِ کد و لایه‌ها تصمیم می‌گیرند، و استدلال دربارهٔ این‌ها آسان است.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;پیش‌فرض‌ها و ریست‌ها را در &lt;code&gt;:where()&lt;/code&gt; بپیچید&lt;/strong&gt; تا بازنویسی‌شان ساده باشد.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;از &lt;code&gt;@layer&lt;/code&gt; استفاده کنید&lt;/strong&gt; تا استایل‌های پایه و کتابخانه‌های بیرونی زیرِ کامپوننت‌هایتان قرار بگیرند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;وقتی قاعده‌ای اعمال نمی‌شود، اول DevTools را نگاه کنید&lt;/strong&gt;: خط خورده است (در آبشار باخته)، نیست (سلکتور منطبق نمی‌شود)، یا با هشدار نشان داده شده (مقدارِ نامعتبر)؟&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;آبشار برنده را به ترتیبی ثابت انتخاب می‌کند: &lt;strong&gt;منشأ و &lt;code&gt;!important&lt;/code&gt;&lt;/strong&gt;، &lt;strong&gt;استایل‌های درون‌خطی&lt;/strong&gt;، &lt;strong&gt;لایه‌ها&lt;/strong&gt;، &lt;strong&gt;specificity&lt;/strong&gt; و بعد &lt;strong&gt;ترتیب ظاهر شدن&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Specificity یعنی &lt;strong&gt;(IDها، کلاس‌ها/attributeها/شبه‌کلاس‌ها، عنصرها/شبه‌عنصرها)&lt;/strong&gt; که ستون‌به‌ستون و بدون انتقال مقایسه می‌شوند.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:is()&lt;/code&gt;، &lt;code&gt;:not()&lt;/code&gt; و &lt;code&gt;:has()&lt;/code&gt; امتیازِ قوی‌ترین آرگومانشان را می‌گیرند؛ &lt;code&gt;:where()&lt;/code&gt; &lt;strong&gt;صفر&lt;/strong&gt; اضافه می‌کند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;مقدارهای به‌ارث‌رسیده&lt;/strong&gt; به هر قاعده‌ای که مستقیماً خودِ عنصر را هدف بگیرد &lt;strong&gt;می‌بازند&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;سلکتورهای کلاسیِ تخت&lt;/strong&gt;، &lt;code&gt;:where()&lt;/code&gt; و &lt;code&gt;@layer&lt;/code&gt; را به IDها و &lt;code&gt;!important&lt;/code&gt; ترجیح دهید.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
    </item>
    <item>
      <title>Stacking Context در CSS: چرا z-index: 9999 کار نمی‌کند</title>
      <link>https://cryo-networks.com/posts/css-stacking-contexts/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/css-stacking-contexts/</guid>
      <pubDate>Thu, 29 Oct 2026 09:00:00 +0000</pubDate>
      <category>CSS</category>
      <description>ویژگی z-index یک رتبه‌بندیِ سراسری نیست. فقط عنصرهای داخل یک stacking context را با هم مقایسه می‌کند، و ده‌ها ویژگی بی‌صدا context تازه می‌سازند. ترتیب رسم را یاد بگیرید، contextی را که عنصرتان در آن گیر افتاده پیدا کنید و باگ‌های هم‌پوشانی را برای همیشه حل کنید.</description>
      <content:encoded>&lt;p&gt;این یکی از رایج‌ترین باگ‌های CSS است. مودال &lt;code&gt;z-index: 9999&lt;/code&gt; دارد. هدر سایت &lt;code&gt;z-index: 10&lt;/code&gt; دارد. و هدر &lt;strong&gt;روی&lt;/strong&gt; مودال رسم می‌شود. 99999 را امتحان می‌کنید، بعد &lt;code&gt;!important&lt;/code&gt; را؛ هیچ چیزی عوض نمی‌شود.&lt;/p&gt;
&lt;p&gt;مرورگر خراب نیست. &lt;code&gt;z-index&lt;/code&gt; رتبه‌بندیِ سراسریِ همهٔ عنصرهای صفحه نیست. فقط عنصرهای &lt;strong&gt;داخل یک stacking context&lt;/strong&gt; را مرتب می‌کند، و مودال شما داخل contextی گیر افتاده که در کل زیرِ هدر قرار دارد. این مقاله توضیح می‌دهد مرورگر چطور تصمیم می‌گیرد چه چیزی رو باشد، چه چیزهایی این contextها را می‌سازند (اغلب تصادفی) و چطور contextی را که باعث باگ شده پیدا و درست کنید. فرض بر این است که با آبشار (&lt;a href=&#34;/posts/css-cascade-specificity/&#34;&gt;آبشار و Specificity در CSS&lt;/a&gt;) و موقعیت‌دهی (positioning) راحت هستید.&lt;/p&gt;
&lt;h2 id=&#34;باگ&#34;&gt;باگ&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;header&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;site-header&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;…&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;page&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;modal&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;…&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;site-header&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;sticky&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;top&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;z-index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;relative&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;z-index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;modal&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;fixed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;inset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;z-index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;9999&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;مودال زیرِ هدر رسم می‌شود. برای فهمیدنِ دلیلش به دو ایده نیاز داریم: &lt;strong&gt;ترتیب رسم&lt;/strong&gt; داخل یک stacking context، و اینکه contextها چطور &lt;strong&gt;تودرتو&lt;/strong&gt; می‌شوند.&lt;/p&gt;
&lt;h2 id=&#34;ترتیب-رسم-داخل-یک-stacking-context&#34;&gt;ترتیب رسم داخل یک stacking context&lt;/h2&gt;
&lt;p&gt;stacking context گروهی از عنصرهاست که مرورگر آن‌ها را با هم و به‌عنوان یک واحد رسم می‌کند. داخل هر کدام، ترتیب رسم از پایین به بالا این است:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;پس‌زمینه و حاشیه‌های&lt;/strong&gt; عنصری که context را می‌سازد&lt;/li&gt;
&lt;li&gt;نوادگانِ &lt;strong&gt;موقعیت‌دار&lt;/strong&gt; با &lt;code&gt;z-index&lt;/code&gt; &lt;strong&gt;منفی&lt;/strong&gt; (منفی‌ترین اول)&lt;/li&gt;
&lt;li&gt;جعبه‌های &lt;strong&gt;بلوکیِ&lt;/strong&gt; معمولی، به ترتیب سند&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;floatها&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;محتوای &lt;strong&gt;درون‌خطی&lt;/strong&gt;: متن، تصویرها، inline-blockها&lt;/li&gt;
&lt;li&gt;نوادگانِ موقعیت‌دار با &lt;code&gt;z-index: auto&lt;/code&gt; یا &lt;code&gt;0&lt;/code&gt;، به ترتیب سند&lt;/li&gt;
&lt;li&gt;نوادگانِ موقعیت‌دار با &lt;code&gt;z-index&lt;/code&gt; &lt;strong&gt;مثبت&lt;/strong&gt;، از کوچک‌ترین&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;دو پیامد آدم‌ها را غافلگیر می‌کند. اول، &lt;strong&gt;عنصرهای موقعیت‌دار حتی بدون هیچ &lt;code&gt;z-index&lt;/code&gt;ی بالای عنصرهای بدون موقعیت رسم می‌شوند&lt;/strong&gt;: اضافه کردنِ تنهای &lt;code&gt;position: relative&lt;/code&gt; می‌تواند یک عنصر را به جلو بیاورد. دوم، &lt;code&gt;z-index&lt;/code&gt; فقط روی &lt;strong&gt;عنصرهای موقعیت‌دار&lt;/strong&gt; (&lt;code&gt;relative&lt;/code&gt;، &lt;code&gt;absolute&lt;/code&gt;، &lt;code&gt;fixed&lt;/code&gt;، &lt;code&gt;sticky&lt;/code&gt;) و &lt;strong&gt;آیتم‌های flex و grid&lt;/strong&gt; اثر دارد. روی یک بلوکِ ایستای معمولی نادیده گرفته می‌شود.&lt;/p&gt;
&lt;h2 id=&#34;contextها-مثل-شمارهنسخه-تودرتو-میشوند&#34;&gt;contextها مثل شماره‌نسخه تودرتو می‌شوند&lt;/h2&gt;
&lt;p&gt;قانونِ کلیدی این است: &lt;strong&gt;هر stacking context داخل context والدش به‌عنوان یک لایهٔ واحد رسم می‌شود&lt;/strong&gt;، در جایگاهی که &lt;code&gt;z-index&lt;/code&gt; خودش تعیین می‌کند. هر چیزی داخل آن، درون همان لایه کشیده می‌شود؛ پس یک فرزند هرگز نمی‌تواند از جایگاهِ والدش فرار کند، &lt;code&gt;z-index&lt;/code&gt; خودش هر قدر هم بالا باشد.&lt;/p&gt;
&lt;p&gt;یک مدل ذهنیِ خوب، شماره‌نسخه‌هاست. در مثال ما، context ریشه دو لایه دارد: هدر (10) و &lt;code&gt;.page&lt;/code&gt; (1). عدد 9999 مودال فقط داخل &lt;code&gt;.page&lt;/code&gt; معنا دارد؛ پس جایگاهِ واقعی‌اش چیزی مثل &lt;strong&gt;1.9999&lt;/strong&gt; است:&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;context ریشه هدر را با z-index 10 و main.page را با z-index 1 در خود دارد. z-index 9999 مودال فقط داخل main.page اعمال می‌شود، پس ترتیبِ واقعی‌اش 1.9999 است که از 10 کمتر است&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;مرورگر اول در سطحِ ریشه 10 را با 1 مقایسه می‌کند و هدر برنده می‌شود. عدد 9999 اصلاً هرگز با هدر مقایسه نمی‌شود. کلِ باگ همین است.&lt;/p&gt;
&lt;h2 id=&#34;چه-چیزهایی-stacking-context-میسازند&#34;&gt;چه چیزهایی stacking context می‌سازند&lt;/h2&gt;
&lt;p&gt;این فهرستِ مهم است، چون بیشترِ stacking contextها &lt;strong&gt;تصادفی&lt;/strong&gt; ساخته می‌شوند؛ به‌عنوان اثرِ جانبیِ ویژگی‌ای که به دلیل دیگری اضافه شده:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ویژگی&lt;/th&gt;
&lt;th&gt;وقتی context می‌سازد که…&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;position: relative&lt;/code&gt; / &lt;code&gt;absolute&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;z-index&lt;/code&gt; هر چیزی جز &lt;code&gt;auto&lt;/code&gt; باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;position: fixed&lt;/code&gt; / &lt;code&gt;sticky&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;همیشه&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;آیتمِ&lt;/strong&gt; flex یا grid&lt;/td&gt;
&lt;td&gt;&lt;code&gt;z-index&lt;/code&gt; هر چیزی جز &lt;code&gt;auto&lt;/code&gt; باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;opacity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;کمتر از &lt;code&gt;1&lt;/code&gt; باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;transform&lt;/code&gt;، &lt;code&gt;scale&lt;/code&gt;، &lt;code&gt;rotate&lt;/code&gt;، &lt;code&gt;translate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;هر چیزی جز &lt;code&gt;none&lt;/code&gt; باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;filter&lt;/code&gt;، &lt;code&gt;backdrop-filter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;هر چیزی جز &lt;code&gt;none&lt;/code&gt; باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clip-path&lt;/code&gt;، &lt;code&gt;mask&lt;/code&gt;، &lt;code&gt;perspective&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;هر چیزی جز &lt;code&gt;none&lt;/code&gt; باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mix-blend-mode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;هر چیزی جز &lt;code&gt;normal&lt;/code&gt; باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isolation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;isolate&lt;/code&gt; باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;will-change&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;نامِ یکی از ویژگی‌های بالا را بیاورد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;contain&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;layout&lt;/code&gt;، &lt;code&gt;paint&lt;/code&gt;، &lt;code&gt;strict&lt;/code&gt; یا &lt;code&gt;content&lt;/code&gt; باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;container-type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;size&lt;/code&gt; یا &lt;code&gt;inline-size&lt;/code&gt; باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;به‌علاوهٔ عنصر ریشه (&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;) که همیشه یک context است.&lt;/p&gt;
&lt;p&gt;پس یک انیمیشنِ fade-in (&lt;code&gt;opacity: 0.99&lt;/code&gt; در طول transition)، یک «ترفند کارایی» مثل &lt;code&gt;transform: translateZ(0)&lt;/code&gt; یا یک &lt;code&gt;will-change: transform&lt;/code&gt; روی یک wrapper، هر کدام می‌توانند همهٔ &lt;code&gt;z-index&lt;/code&gt;های داخلشان را گیر بیندازند. علت‌های کلاسیک در دنیای واقعی:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;یک &lt;strong&gt;wrapper انیمیشن‌دار برای صفحه&lt;/strong&gt; با &lt;code&gt;transform&lt;/code&gt; که همهٔ مودال‌ها و منوهای کشویی داخلش را گیر می‌اندازد.&lt;/li&gt;
&lt;li&gt;یک &lt;strong&gt;هدرِ sticky&lt;/strong&gt; در یک بخش از صفحه و یک منوی کشویی داخلِ بخشِ sticky دیگری.&lt;/li&gt;
&lt;li&gt;یک &lt;strong&gt;کارت با &lt;code&gt;opacity: 0.95&lt;/code&gt;&lt;/strong&gt; که tooltipاش زیرِ کارتِ بعدی می‌رود.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;ویژگی transform موقعیتِ fixed را هم خراب می‌کند&lt;/p&gt;
&lt;p&gt;والدی با &lt;code&gt;transform&lt;/code&gt;، &lt;code&gt;filter&lt;/code&gt;، &lt;code&gt;perspective&lt;/code&gt; یا &lt;code&gt;will-change: transform&lt;/code&gt; فقط یک stacking context نمی‌سازد: &lt;strong&gt;بلوکِ دربرگیرنده&lt;/strong&gt; (containing block) برای نوادگانِ &lt;code&gt;position: fixed&lt;/code&gt; هم می‌شود. آن‌وقت مودالِ «fixed» شما به‌جای viewport نسبت به همان والد جای می‌گیرد و با آن اسکرول می‌شود. اگر یک عنصرِ fixed هم جایش اشتباه است &lt;em&gt;و&lt;/em&gt; هم در لایهٔ اشتباه است، دنبال یک transform بگردید.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;پیدا-کردن-contextی-که-گیرتان-انداخته&#34;&gt;پیدا کردنِ contextی که گیرتان انداخته&lt;/h2&gt;
&lt;p&gt;DevTools مستقیماً stacking contextها را نشان نمی‌دهد، اما با چند خط جاوااسکریپت می‌توانید پیدایشان کنید. عنصرِ مشکل‌دار را در پنل Elements انتخاب کنید و بعد این را در کنسول بچسبانید (&lt;code&gt;$0&lt;/code&gt; همان عنصرِ انتخاب‌شده است):&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stackingContexts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;el&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;found&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[];&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;el&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;parentElement&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;parentElement&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getComputedStyle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;parent&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;parentElement&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getComputedStyle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;parentElement&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[];&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;flexOrGridItem&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;sr&#34;&gt;/flex|grid/&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;parent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;?&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;??&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;zIndex&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;auto&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;static&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;flexOrGridItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`z-index: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;zIndex&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;===&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;fixed&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;===&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;sticky&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`position: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;opacity&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`opacity: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;opacity&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prop&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;transform&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;scale&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;rotate&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;translate&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;filter&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;backdropFilter&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;perspective&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;clipPath&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mixBlendMode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;normal&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`mix-blend-mode: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mixBlendMode&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;isolation&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;===&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;isolate&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;isolation: isolate&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sr&#34;&gt;/transform|opacity|filter/&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;willChange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`will-change: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;willChange&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;found&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reasons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;, &amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;found&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stackingContexts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;$0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;این تابع از عنصر به بالا حرکت می‌کند و همهٔ والدهایی را که stacking context می‌سازند، همراه با دلیلش، فهرست می‌کند. علت‌های رایج را پوشش می‌دهد، نه تک‌تکِ قاعده‌های جدول را. &lt;strong&gt;اولین&lt;/strong&gt; ردیف همان contextی است که &lt;code&gt;z-index&lt;/code&gt; شما در آن گیر افتاده؛ &lt;code&gt;z-index&lt;/code&gt; عنصری را که با آن درگیرید با &lt;code&gt;z-index&lt;/code&gt; &lt;em&gt;همان&lt;/em&gt; والد مقایسه کنید، نه با &lt;code&gt;z-index&lt;/code&gt; خودتان.&lt;/p&gt;
&lt;h2 id=&#34;درست-کردنش&#34;&gt;درست کردنش&lt;/h2&gt;
&lt;p&gt;وقتی فهمیدید کدام context عنصر را گیر انداخته، راه‌حلی را انتخاب کنید که با علت جور است:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;۱. context تصادفی را حذف کنید.&lt;/strong&gt; اگر &lt;code&gt;.page&lt;/code&gt; واقعاً به &lt;code&gt;z-index: 1&lt;/code&gt; (یا آن &lt;code&gt;transform&lt;/code&gt; یا &lt;code&gt;will-change&lt;/code&gt;) نیاز ندارد، پاکش کنید. وقتی آن ویژگی «محض احتیاط» اضافه شده، این بهترین راه‌حل است.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;۲. عنصر را بیرون ببرید.&lt;/strong&gt; لایه‌های رویی مثل مودال‌ها، toastها و منوهای کشویی بهتر است فرزندِ مستقیمِ &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; رندر شوند، بیرون از context همهٔ کامپوننت‌ها. بیشترِ فریم‌ورک‌های رابط کاربری ابزاری برای این دارند: &lt;code&gt;createPortal&lt;/code&gt; در React، &lt;code&gt;&amp;lt;Teleport&amp;gt;&lt;/code&gt; در Vue و کتابخانه‌های portal در Svelte.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;۳. از لایهٔ بالایی استفاده کنید.&lt;/strong&gt; مرورگرهای مدرن یک &lt;strong&gt;لایهٔ بالایی&lt;/strong&gt; (top layer) دارند که بالای کلِ سند و بیرون از همهٔ stacking contextها قرار دارد. عنصرها از طریق APIهای خودِ پلتفرم به آنجا می‌رسند؛ پس اصلاً به &lt;code&gt;z-index&lt;/code&gt; نیازی نیست:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;dialog&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;confirm&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Delete this file?&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;form&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;method&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;dialog&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Cancel&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;ok&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;form&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getElementById&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;confirm&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;showModal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// rendered in the top layer&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;ی که با &lt;code&gt;showModal()&lt;/code&gt; باز شود، عنصرهایی با ویژگیِ &lt;code&gt;popover&lt;/code&gt; و عنصرهای تمام‌صفحه، همه در لایهٔ بالایی رندر می‌شوند، هر جای DOM که باشند. &lt;code&gt;showModal()&lt;/code&gt; یک &lt;code&gt;::backdrop&lt;/code&gt; هم اضافه می‌کند، فوکوس را داخل دیالوگ نگه می‌دارد و با &lt;kbd&gt;Esc&lt;/kbd&gt; بسته می‌شود؛ چیزهایی که یک مودالِ دست‌ساز معمولاً اشتباه پیاده می‌کند.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;۴. کلِ context را بالا ببرید.&lt;/strong&gt; اگر هیچ‌کدام از این‌ها جواب نداد، &lt;code&gt;z-index&lt;/code&gt; &lt;strong&gt;ریشهٔ context&lt;/strong&gt; (یعنی &lt;code&gt;.page&lt;/code&gt;) را عوض کنید، نه عنصرِ داخلش را. یادتان باشد این کار همه‌چیزِ داخلِ &lt;code&gt;.page&lt;/code&gt; را هم با خودش جابه‌جا می‌کند.&lt;/p&gt;
&lt;h2 id=&#34;ویژگی-isolation-isolate-نوع-مفید-context&#34;&gt;ویژگی isolation: isolate، نوعِ مفیدِ context&lt;/h2&gt;
&lt;p&gt;گاهی &lt;em&gt;می‌خواهید&lt;/em&gt; یک stacking context داشته باشید. یک مثالِ رایج، لایه‌ای تزئینی پشتِ محتوای یک کارت است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;card&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;relative&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;white&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;card&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;before&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;absolute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;inset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;-4&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;z-index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;-1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                 &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* behind the card&amp;#39;s content... */&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;linear-gradient&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;135&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;deg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;violet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;orange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;border-radius&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;inherit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;بدون stacking context روی &lt;code&gt;.card&lt;/code&gt;، شبه‌عنصرِ &lt;code&gt;::before&lt;/code&gt; با &lt;code&gt;z-index: -1&lt;/code&gt; در هر contextی که کارت در آن است، در مرحلهٔ ۲ِ ترتیب رسم کشیده می‌شود: &lt;strong&gt;زیرِ پس‌زمینهٔ سفیدِ خودِ کارت&lt;/strong&gt;. هالهٔ رنگی پشتِ همان کارتی پنهان می‌شود که قرار بود قابش باشد، و حتی ممکن است پشتِ پس‌زمینهٔ والدهای کارت هم برود.&lt;/p&gt;
&lt;p&gt;به کارت context خودش را بدهید تا مشکل از بین برود:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;card&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;relative&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;white&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;isolation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;isolate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;حالا &lt;code&gt;::before&lt;/code&gt; داخلِ context کارت رسم می‌شود: بالای پس‌زمینهٔ کارت و زیرِ محتوایش. &lt;code&gt;isolation: isolate&lt;/code&gt; دقیقاً برای همین وجود دارد. یک context می‌سازد و هیچ کار دیگری نمی‌کند: نه موقعیت‌دهی، نه مقدارِ &lt;code&gt;z-index&lt;/code&gt;ی که باید مدیریتش کنید، نه اثر جانبی.&lt;/p&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;یک مقیاسِ z-index برای بقیه&lt;/p&gt;
&lt;p&gt;برای عنصرهایی که واقعاً در یک context مشترک‌اند، از مسابقهٔ عددهای بزرگ‌تر و بزرگ‌تر پرهیز کنید. یک مقیاسِ کوچک را یک بار تعریف کنید، مثلاً &lt;code&gt;--z-dropdown: 10; --z-sticky: 20; --z-overlay: 30; --z-toast: 40;&lt;/code&gt;، و فقط از همین مقدارها استفاده کنید. اگر چیزی باید بین دو سطح قرار بگیرد، این یک تصمیمِ طراحی است، نه عددی برای از خود درآوردن.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;z-index&lt;/code&gt; فقط عنصرهای &lt;strong&gt;داخل یک stacking context&lt;/strong&gt; را مرتب می‌کند؛ contextها تودرتو می‌شوند، پس با شماره‌نسخه فکر کنید: &lt;strong&gt;1.9999 &amp;lt; 10&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;ترتیب رسم داخل یک context این است: پس‌زمینه، &lt;code&gt;z-index&lt;/code&gt; منفی، بلوک‌ها، floatها، محتوای درون‌خطی، &lt;code&gt;z-index: auto&lt;/code&gt;/&lt;code&gt;0&lt;/code&gt; و &lt;code&gt;z-index&lt;/code&gt; مثبت.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;z-index&lt;/code&gt; فقط روی &lt;strong&gt;عنصرهای موقعیت‌دار و آیتم‌های flex/grid&lt;/strong&gt; کار می‌کند.&lt;/li&gt;
&lt;li&gt;ویژگی‌های زیادی به‌عنوان اثر جانبی context می‌سازند: &lt;strong&gt;&lt;code&gt;opacity&lt;/code&gt; کمتر از ۱، &lt;code&gt;transform&lt;/code&gt;، &lt;code&gt;filter&lt;/code&gt;، &lt;code&gt;will-change&lt;/code&gt;، موقعیتِ fixed/sticky&lt;/strong&gt; و بیشتر.&lt;/li&gt;
&lt;li&gt;باگ‌های هم‌پوشانی را با حذفِ contextهای تصادفی، بردنِ لایه‌های رویی به &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; یا استفاده از &lt;strong&gt;لایهٔ بالایی&lt;/strong&gt; (&lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;، &lt;code&gt;popover&lt;/code&gt;) حل کنید. وقتی عمداً یک context می‌خواهید، از &lt;strong&gt;&lt;code&gt;isolation: isolate&lt;/code&gt;&lt;/strong&gt; استفاده کنید.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
    </item>
    <item>
      <title>لیست کامپرهنشن در پایتون: از حلقه تا یک‌خطی‌های زیبا</title>
      <link>https://cryo-networks.com/posts/python-list-comprehensions/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/python-list-comprehensions/</guid>
      <pubDate>Mon, 26 Oct 2026 09:00:00 +0000</pubDate>
      <category>پایتون</category>
      <description>یاد بگیرید لیست کامپرهنشن چطور کار می‌کند، کِی کدتان را خواناتر می‌کند و کِی همان حلقهٔ for ساده انتخاب بهتری است.</description>
      <content:encoded>&lt;p&gt;اگر کد پایتونِ دیگران را خوانده باشید، تقریباً حتماً چیزی شبیه این دیده‌اید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;squares&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;این یک &lt;strong&gt;لیست کامپرهنشن&lt;/strong&gt; (List Comprehension) است: روشی فشرده برای ساختن یک لیست جدید از روی یک مجموعهٔ قابل پیمایش. وقتی مفهومش جا بیفتد، مدام از آن استفاده خواهید کرد. در این راهنما از همان حلقهٔ &lt;code&gt;for&lt;/code&gt; که می‌شناسید شروع می‌کنیم، فیلتر کردن و تبدیل داده را می‌بینیم، سراغ کامپرهنشنِ دیکشنری و مجموعه می‌رویم و در پایان می‌گوییم کِی &lt;em&gt;نباید&lt;/em&gt; از آن استفاده کنید.&lt;/p&gt;
&lt;h2 id=&#34;از-حلقهای-که-میشناسید-شروع-کنید&#34;&gt;از حلقه‌ای که می‌شناسید شروع کنید&lt;/h2&gt;
&lt;p&gt;روش کلاسیک ساختن لیستی از مربع‌ها این است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;squares&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;squares&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;squares&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;سه خط و سه کار: ساختن یک لیست خالی، پیمایش و افزودن. کامپرهنشن همین ایده را در یک خط بیان می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;squares&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;آن را این‌طور بخوانید: &lt;em&gt;«به ازای هر &lt;code&gt;n&lt;/code&gt; در &lt;code&gt;range(10)&lt;/code&gt;، مقدار &lt;code&gt;n * n&lt;/code&gt; را به من بده.»&lt;/em&gt; عبارتی که می‌خواهید جمع شود اول می‌آید و بعد حلقه‌ای که مقادیر را تولید می‌کند.&lt;/p&gt;
&lt;h2 id=&#34;اجزای-یک-کامپرهنشن&#34;&gt;اجزای یک کامپرهنشن&lt;/h2&gt;
&lt;p&gt;هر لیست کامپرهنشن از این الگو پیروی می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;[expression for item in iterable if condition]&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;همین سه بخش در یک کامپرهنشن واقعی که اعداد زوجِ کمتر از ۱۰ را به توان دو می‌رساند&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;بخش&lt;/th&gt;
&lt;th&gt;معنی&lt;/th&gt;
&lt;th&gt;الزامی؟&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;expression&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;چیزی که در لیست جدید قرار می‌گیرد&lt;/td&gt;
&lt;td&gt;بله&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for item in iterable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;مقادیر از کجا می‌آیند&lt;/td&gt;
&lt;td&gt;بله&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;if condition&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;فقط آیتم‌هایی که شرط را دارند نگه داشته می‌شوند&lt;/td&gt;
&lt;td&gt;خیر&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;فیلتر-کردن-با-if&#34;&gt;فیلتر کردن با &lt;code&gt;if&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;برای نگه داشتن فقط بعضی آیتم‌ها، یک شرط به انتها اضافه کنید. این‌جا اعداد زوج را نگه می‌داریم:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;evens&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;می‌توانید هم‌زمان تبدیل و فیلتر کنید. این کد طول کلمه‌هایی را که بیش از سه حرف دارند جمع می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;git&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;python&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;sql&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;linux&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;css&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;docker&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;long_word_lengths&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;w&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;w&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;words&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;w&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# [6, 5, 6]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;انتخاب-مقدار-با-if-else&#34;&gt;انتخاب مقدار با &lt;code&gt;if ... else&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;اگر بخواهید &lt;em&gt;همهٔ&lt;/em&gt; آیتم‌ها را نگه دارید اما بعضی‌شان را تغییر دهید چه؟ یک &lt;code&gt;if ... else&lt;/code&gt; را &lt;strong&gt;قبل از&lt;/strong&gt; &lt;code&gt;for&lt;/code&gt; بگذارید. این عبارت شرطیِ پایتون است، نه فیلتر:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;scores&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;92&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;47&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;78&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;85&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;pass&amp;quot;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;fail&amp;quot;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scores&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# [&amp;#39;pass&amp;#39;, &amp;#39;fail&amp;#39;, &amp;#39;pass&amp;#39;, &amp;#39;fail&amp;#39;, &amp;#39;pass&amp;#39;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;قانون جایگاه را به خاطر بسپارید&lt;/p&gt;
&lt;p&gt;&lt;code&gt;if&lt;/code&gt; &lt;strong&gt;بعد از&lt;/strong&gt; &lt;code&gt;for&lt;/code&gt; آیتم‌ها را حذف می‌کند. &lt;code&gt;if ... else&lt;/code&gt; &lt;strong&gt;قبل از&lt;/strong&gt; &lt;code&gt;for&lt;/code&gt; تعیین می‌کند هر آیتم به چه چیزی تبدیل شود. اولی می‌تواند لیست را کوتاه‌تر کند؛ دومی هرگز.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;مثالهای-واقعی&#34;&gt;مثال‌های واقعی&lt;/h2&gt;
&lt;p&gt;کامپرهنشن‌ها وقتی داده را تمیز یا بازآرایی می‌کنید می‌درخشند.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;یکدست کردن ورودی کاربر:&lt;/strong&gt;&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;raw_emails&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;  Ada@Example.com&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;grace@example.com  &amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;LINUS@example.com&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;emails&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;strip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;raw_emails&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;strip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# [&amp;#39;ada@example.com&amp;#39;, &amp;#39;grace@example.com&amp;#39;, &amp;#39;linus@example.com&amp;#39;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;بیرون کشیدن یک فیلد از لیستی از دیکشنری‌ها:&lt;/strong&gt;&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;users&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;active&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;Grace&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;active&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;Linus&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;active&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;active_names&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;u&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;users&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;active&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# [&amp;#39;Ada&amp;#39;, &amp;#39;Linus&amp;#39;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;تخت کردن یک لیست تودرتو.&lt;/strong&gt; حلقه‌ها به همان ترتیبی می‌آیند که در دستورهای &lt;code&gt;for&lt;/code&gt; تودرتو می‌آمدند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;matrix&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;flat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;matrix&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# [1, 2, 3, 4, 5, 6, 7, 8, 9]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;کامپرهنشن-دیکشنری-و-مجموعه&#34;&gt;کامپرهنشنِ دیکشنری و مجموعه&lt;/h2&gt;
&lt;p&gt;همین سینتکس با آکولاد هم کار می‌کند. برای ساختن دیکشنری از &lt;code&gt;key: value&lt;/code&gt; استفاده کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;git&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;python&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;sql&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;lengths&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;w&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;w&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;w&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# {&amp;#39;git&amp;#39;: 3, &amp;#39;python&amp;#39;: 6, &amp;#39;sql&amp;#39;: 3}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;دونقطه را حذف کنید تا یک مجموعه (set) بگیرید که تکراری‌ها را خودکار حذف می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;unique_lengths&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;w&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;w&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# {3, 6}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;generator-expression-کامپرهنشن-بدون-لیست&#34;&gt;Generator Expression: کامپرهنشن بدون لیست&lt;/h2&gt;
&lt;p&gt;اگر کروشه‌ها را با پرانتز عوض کنید، یک &lt;strong&gt;generator expression&lt;/strong&gt; دارید. این عبارت به‌جای ساختن کل لیست در حافظه، مقادیر را یکی‌یکی تولید می‌کند؛ مناسب وقتی که فقط یک بار به مقادیر نیاز دارید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1_000_000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;وقتی generator expression تنها آرگومانِ یک تابع باشد، مثل بالا می‌توانید پرانتزهای اضافه را حذف کنید. توابعی مثل &lt;code&gt;sum()&lt;/code&gt;، &lt;code&gt;any()&lt;/code&gt;، &lt;code&gt;all()&lt;/code&gt;، &lt;code&gt;max()&lt;/code&gt; و &lt;code&gt;min()&lt;/code&gt; با آن‌ها عالی کار می‌کنند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;has_admin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;role&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;admin&amp;quot;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;u&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;users&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;کی-کامپرهنشن-ننویسیم&#34;&gt;کِی کامپرهنشن &lt;em&gt;ننویسیم&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;کامپرهنشن‌ها برای خواناتر کردن کد هستند. اگر کدی خوانایی‌اش را از دست داد، از حلقه استفاده کنید. مراقب این نشانه‌ها باشید:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;در یکی دو خط به‌راحتی جا نمی‌شود.&lt;/strong&gt; کامپرهنشن‌های تودرتو با چند شرط به‌سختی خوانده می‌شوند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;به اثر جانبی نیاز دارید.&lt;/strong&gt; ننویسید &lt;code&gt;[print(x) for x in items]&lt;/code&gt;. این کار لیستی دورریختنی از &lt;code&gt;None&lt;/code&gt; می‌سازد. از حلقهٔ &lt;code&gt;for&lt;/code&gt; استفاده کنید.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;برای هر آیتم به &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;except&lt;/code&gt; یا چند دستور نیاز دارید.&lt;/strong&gt; کامپرهنشن فقط یک عبارت را در خود جا می‌دهد؛ یک حلقه یا یک تابع کمکی واضح‌تر است.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;c1&#34;&gt;# Hard to read: avoid&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Clearer: give the logic a name&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;odd_pair_products&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;limit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;limit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;yield&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;odd_pair_products&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[expr for x in items]&lt;/code&gt; همهٔ آیتم‌ها را تبدیل می‌کند.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[expr for x in items if cond]&lt;/code&gt; فیلتر هم می‌کند.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[a if cond else b for x in items]&lt;/code&gt; برای هر آیتم یک مقدار انتخاب می‌کند.&lt;/li&gt;
&lt;li&gt;برای دیکشنری از &lt;code&gt;{k: v ...}&lt;/code&gt;، برای مجموعه از &lt;code&gt;{x ...}&lt;/code&gt; و برای generatorهای تنبل از &lt;code&gt;(x ...)&lt;/code&gt; استفاده کنید.&lt;/li&gt;
&lt;li&gt;اگر کد دارد بیش از حد زیرکانه می‌شود، حلقه معمولاً با خوانندهٔ بعدی مهربان‌تر است؛ خواننده‌ای که شاید خودتان باشید.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;تمرین:&lt;/strong&gt; یکی از اسکریپت‌هایی را که اخیراً نوشته‌اید باز کنید و دنبال الگوی «لیست خالی، حلقه، append» بگردید. آن را به کامپرهنشن تبدیل کنید و صادقانه تصمیم بگیرید کدام نسخه خواناتر است.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>درک async/await در جاوااسکریپت</title>
      <link>https://cryo-networks.com/posts/javascript-async-await/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/javascript-async-await/</guid>
      <pubDate>Wed, 21 Oct 2026 09:00:00 +0000</pubDate>
      <category>جاوااسکریپت</category>
      <description>راهنمایی کاربردی دربارهٔ پرامیس‌ها و async/await: چطور کار می‌کنند، خطاها را چطور مدیریت کنیم و کارها را چطور موازی اجرا کنیم تا برنامه کند نشود.</description>
      <content:encoded>&lt;p&gt;جاوااسکریپت کد شما را روی یک رشته (thread) اجرا می‌کند، با این حال می‌تواند فایل دانلود کند، منتظر تایمرها بماند و با پایگاه داده حرف بزند بی‌آنکه قفل شود. راز این کار کد &lt;strong&gt;ناهمگام&lt;/strong&gt; (asynchronous) است و &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; خواناترین راه برای نوشتن آن است.&lt;/p&gt;
&lt;p&gt;در این مقاله یاد می‌گیرید پرامیس واقعاً چیست، &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; چطور روی آن بنا شده، خطاها را چطور درست مدیریت کنید و چطور از رایج‌ترین اشتباهِ عملکردیِ برنامه‌نویسان دوری کنید.&lt;/p&gt;
&lt;h2 id=&#34;مسئله-منتظر-ماندن-بدون-مسدود-کردن&#34;&gt;مسئله: منتظر ماندن بدون مسدود کردن&lt;/h2&gt;
&lt;p&gt;فرض کنید می‌خواهید اطلاعات یک کاربر را از یک API بگیرید. شبکه ممکن است ۳۰۰ میلی‌ثانیه طول بکشد. اگر جاوااسکریپت همان‌جا &lt;em&gt;می‌ایستاد&lt;/em&gt; و صبر می‌کرد، کل صفحه قفل می‌شد: نه کلیکی، نه اسکرولی، نه انیمیشنی.&lt;/p&gt;
&lt;p&gt;در عوض، توابع ناهمگام بلافاصله یک &lt;strong&gt;پرامیس&lt;/strong&gt; (Promise) برمی‌گردانند؛ شیئی که نمایندهٔ مقداری است که &lt;em&gt;بعداً&lt;/em&gt; در دسترس خواهد بود.&lt;/p&gt;
&lt;h2 id=&#34;پرامیس-در-۶۰-ثانیه&#34;&gt;پرامیس در ۶۰ ثانیه&lt;/h2&gt;
&lt;p&gt;هر پرامیس همیشه در یکی از سه حالت است:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;pending&lt;/strong&gt; (در انتظار): کار هنوز در جریان است&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fulfilled&lt;/strong&gt; (انجام‌شده): کار با موفقیت و با یک مقدار تمام شده&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rejected&lt;/strong&gt; (ردشده): کار با یک خطا شکست خورده&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;با &lt;code&gt;.then()&lt;/code&gt; و &lt;code&gt;.catch()&lt;/code&gt; به پرامیس واکنش نشان می‌دهید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;https://api.github.com/users/octocat&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;catch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Request failed:&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;این روش کار می‌کند، اما با بزرگ‌تر شدن منطق، دنبال کردن زنجیره‌ها سخت می‌شود؛ مخصوصاً وقتی هر مرحله به نتیجهٔ مرحلهٔ قبل وابسته است.&lt;/p&gt;
&lt;h2 id=&#34;ورود-asyncawait&#34;&gt;ورود async/await&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; سینتکسی است که روی پرامیس‌ها ساخته شده. با آن می‌توانید کد ناهمگامی بنویسید که مثل کد همگام &lt;em&gt;خوانده&lt;/em&gt; می‌شود:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;showUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`https://api.github.com/users/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;nx&#34;&gt;showUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;octocat&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;دو قانون این کار را ممکن می‌کند:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;async&lt;/code&gt; قبل از تابع&lt;/strong&gt; باعث می‌شود تابع همیشه یک پرامیس برگرداند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;await&lt;/code&gt; همان تابع را متوقف می‌کند&lt;/strong&gt; تا پرامیس به نتیجه برسد و بعد مقدارش را به شما می‌دهد. در این فاصله بقیهٔ کدها اجرا می‌شوند؛ فقط &lt;em&gt;همین&lt;/em&gt; تابع منتظر می‌ماند.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;admonition note&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;await صفحه را قفل نمی‌کند&lt;/p&gt;
&lt;p&gt;وقتی &lt;code&gt;showUser&lt;/code&gt; روی یک &lt;code&gt;await&lt;/code&gt; متوقف است، مرورگر آزاد است کلیک‌ها را پردازش کند، توابع دیگر را اجرا کند و صفحه را دوباره رسم کند. تابع پس از به نتیجه رسیدن پرامیس ادامه پیدا می‌کند.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;مدیریت-خطا-با-trycatch&#34;&gt;مدیریت خطا با try/catch&lt;/h2&gt;
&lt;p&gt;در زنجیره‌های &lt;code&gt;.then()&lt;/code&gt; از &lt;code&gt;.catch()&lt;/code&gt; استفاده می‌کنید. با &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; از همان &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;catch&lt;/code&gt; آشنا استفاده می‌کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`https://api.github.com/users/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;throw&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;ow&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`HTTP &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;catch&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`Could not load &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;:`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;fetch فقط در خطای شبکه رد می‌شود&lt;/p&gt;
&lt;p&gt;پاسخ &lt;code&gt;404&lt;/code&gt; یا &lt;code&gt;500&lt;/code&gt; پرامیسِ &lt;code&gt;fetch()&lt;/code&gt; را رد &lt;strong&gt;نمی‌کند&lt;/strong&gt;. همیشه خودتان &lt;code&gt;response.ok&lt;/code&gt; (یا &lt;code&gt;response.status&lt;/code&gt;) را بررسی کنید، همان‌طور که بالا دیدید.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;اشتباه-شماره-۱-کدی-که-ناخواسته-پشتسرهم-اجرا-میشود&#34;&gt;اشتباه شمارهٔ ۱: کدی که ناخواسته پشت‌سرهم اجرا می‌شود&lt;/h2&gt;
&lt;p&gt;به این تابع نگاه کنید. مشکلش را می‌بینید؟&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;loadDashboard&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;octocat&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// ~300 ms&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;repos&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getRepos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;octocat&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// ~300 ms&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;events&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getEvents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;octocat&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// ~300 ms&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;repos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;events&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// total: ~900 ms&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;هر درخواست منتظر می‌ماند تا قبلی تمام شود، در حالی که هیچ‌کدام به دیگری وابسته نیستند! همه را هم‌زمان شروع کنید و با &lt;code&gt;Promise.all()&lt;/code&gt; با هم منتظرشان بمانید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;loadDashboard&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;repos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;events&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;octocat&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getRepos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;octocat&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getEvents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;octocat&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;repos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;events&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// total: ~300 ms&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;همان نتیجه، تقریباً سه برابر سریع‌تر.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;منتظر ماندنِ تک‌تکِ درخواست‌های مستقل زمان‌هایشان را جمع می‌کند؛ Promise.all آن‌ها را هم‌زمان اجرا می‌کند&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&#34;انتخاب-ترکیبکننده-مناسب-پرامیس&#34;&gt;انتخاب ترکیب‌کنندهٔ مناسب پرامیس&lt;/h2&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;متد&lt;/th&gt;
&lt;th&gt;انجام می‌شود وقتی…&lt;/th&gt;
&lt;th&gt;رد می‌شود وقتی…&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.all()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;همهٔ&lt;/strong&gt; پرامیس‌ها انجام شوند&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;هر کدام&lt;/strong&gt; رد شود&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.allSettled()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;همهٔ پرامیس‌ها به نتیجه برسند&lt;/td&gt;
&lt;td&gt;هرگز&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.race()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;اولین پرامیسی که به نتیجه می‌رسد انجام شود&lt;/td&gt;
&lt;td&gt;اولین پرامیسی که به نتیجه می‌رسد رد شود&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.any()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;اولین&lt;/strong&gt; پرامیس انجام شود&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;همهٔ&lt;/strong&gt; پرامیس‌ها رد شوند&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;وقتی همهٔ نتیجه‌ها را می‌خواهید حتی اگر بعضی شکست بخورند، از &lt;code&gt;Promise.allSettled()&lt;/code&gt; استفاده کنید؛ مثلاً برای بارگذاری چند ویجت اختیاری:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;allSettled&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getRepos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;octocat&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getEvents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;octocat&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]);&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;===&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;fulfilled&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;render&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;warn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Widget failed:&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reason&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;افزودن-مهلت-زمانی-timeout&#34;&gt;افزودن مهلت زمانی (Timeout)&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;fetch()&lt;/code&gt; به‌طور پیش‌فرض مهلت زمانی ندارد. در مرورگرهای مدرن و Node.js نسخهٔ ۱۸ به بعد، &lt;code&gt;AbortSignal.timeout()&lt;/code&gt; آن را در یک خط به شما می‌دهد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fetchWithTimeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ms&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;5000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;signal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;AbortSignal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;timeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ms&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;throw&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;ow&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`HTTP &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;اگر درخواست بیش از &lt;code&gt;ms&lt;/code&gt; میلی‌ثانیه طول بکشد، پرامیس با یک &lt;code&gt;TimeoutError&lt;/code&gt; رد می‌شود که می‌توانید مثل هر خطای دیگری در &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;catch&lt;/code&gt; مدیریتش کنید.&lt;/p&gt;
&lt;h2 id=&#34;حلقهها-و-await&#34;&gt;حلقه‌ها و await&lt;/h2&gt;
&lt;p&gt;استفاده از &lt;code&gt;await&lt;/code&gt; داخل حلقهٔ &lt;code&gt;for...of&lt;/code&gt; آیتم‌ها را &lt;strong&gt;یکی‌یکی&lt;/strong&gt; پردازش می‌کند. این دقیقاً همان چیزی است که وقتی ترتیب مهم است یا نباید یک API را زیر بار ببرید، لازم دارید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;orderIds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;processOrder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// waits for each one before starting the next&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;وقتی کارها مستقل‌اند، آن‌ها را به پرامیس تبدیل کنید و با هم منتظرشان بمانید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;orderIds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;processOrder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition danger&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;forEach منتظر نمی‌ماند&lt;/p&gt;
&lt;p&gt;&lt;code&gt;orderIds.forEach(async (id) =&amp;gt; await processOrder(id))&lt;/code&gt; منتظر &lt;strong&gt;هیچ&lt;/strong&gt; چیزی نمی‌ماند، چون &lt;code&gt;forEach&lt;/code&gt; پرامیس‌هایی را که تابعِ شما برمی‌گرداند نادیده می‌گیرد. به‌جای آن از &lt;code&gt;for...of&lt;/code&gt; یا &lt;code&gt;Promise.all()&lt;/code&gt; استفاده کنید.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;پرامیس&lt;/strong&gt; نمایندهٔ یک مقدار در آینده است: در انتظار، انجام‌شده یا ردشده.&lt;/li&gt;
&lt;li&gt;توابع &lt;strong&gt;&lt;code&gt;async&lt;/code&gt;&lt;/strong&gt; همیشه پرامیس برمی‌گردانند؛ &lt;strong&gt;&lt;code&gt;await&lt;/code&gt;&lt;/strong&gt; فقط همان تابع را متوقف می‌کند.&lt;/li&gt;
&lt;li&gt;برای خطاها از &lt;strong&gt;&lt;code&gt;try&lt;/code&gt;/&lt;code&gt;catch&lt;/code&gt;&lt;/strong&gt; استفاده کنید و یادتان باشد با &lt;code&gt;fetch()&lt;/code&gt; مقدار &lt;code&gt;response.ok&lt;/code&gt; را بررسی کنید.&lt;/li&gt;
&lt;li&gt;کارهای مستقل را با &lt;strong&gt;&lt;code&gt;Promise.all()&lt;/code&gt;&lt;/strong&gt; موازی اجرا کنید، نه اینکه یکی‌یکی منتظرشان بمانید.&lt;/li&gt;
&lt;li&gt;هرگز به &lt;strong&gt;&lt;code&gt;forEach&lt;/code&gt;&lt;/strong&gt; برای منتظر ماندنِ callbackهای ناهمگام تکیه نکنید.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;دفعهٔ بعد که &lt;code&gt;await&lt;/code&gt; می‌نویسید، از خودتان بپرسید: &lt;em&gt;آیا این خط واقعاً باید منتظر خط بالایی بماند؟&lt;/em&gt; همین یک سؤال برنامه‌هایتان را به‌طور محسوسی سریع‌تر می‌کند.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>روش کاری عملی با برنچ‌های گیت برای مبتدی‌ها</title>
      <link>https://cryo-networks.com/posts/git-branching-workflow/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/git-branching-workflow/</guid>
      <pubDate>Wed, 14 Oct 2026 09:00:00 +0000</pubDate>
      <category>گیت</category>
      <description>دیگر همه‌چیز را روی main کامیت نکنید. یک روش کاری ساده و تیمی با برنچ‌های فیچر، پول ریکوئست و ادغامِ تمیز یاد بگیرید.</description>
      <content:encoded>&lt;p&gt;وقتی تازه گیت را یاد می‌گیرید، طبیعی است که همه‌چیز را مستقیم روی &lt;code&gt;main&lt;/code&gt; کامیت کنید. این روش جواب می‌دهد، تا وقتی که مجبور شوید وسط کار روی یک فیچر باگی را درست کنید یا هم‌تیمی‌تان تغییراتی را پوش کند که با تغییرات شما تداخل دارد.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;برنچ‌ها&lt;/strong&gt; (branch) این مشکل را حل می‌کنند. در این راهنما روش کاری ساده‌ای را یاد می‌گیرید که تیم‌هایی در هر اندازه از آن استفاده می‌کنند: برای هر کار یک برنچ بسازید، آزادانه کامیت کنید و وقتی آماده شد آن را ادغام کنید.&lt;/p&gt;
&lt;h2 id=&#34;برنچ-واقعا-چیست&#34;&gt;برنچ واقعاً چیست&lt;/h2&gt;
&lt;p&gt;برنچ در گیت فقط یک &lt;strong&gt;اشاره‌گر متحرک به یک کامیت&lt;/strong&gt; است. ساختنش آنی است و تقریباً هزینه‌ای ندارد، چون گیت فایل‌هایتان را کپی نمی‌کند. وقتی کامیت جدیدی می‌سازید، برنچی که روی آن هستید جلو می‌رود و به کامیت جدید اشاره می‌کند.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;یک برنچ فیچر از main جدا می‌شود، کامیت‌های خودش را می‌گیرد و دوباره ادغام می‌شود&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;این‌جا &lt;code&gt;feature/login&lt;/code&gt; بعد از کامیت &lt;code&gt;C&lt;/code&gt; از &lt;code&gt;main&lt;/code&gt; جدا می‌شود و دو کامیتِ مخصوص خودش، &lt;code&gt;D&lt;/code&gt; و &lt;code&gt;E&lt;/code&gt;، را می‌گیرد. کار روی یک برنچ تا وقتی ادغام نکنید روی برنچ دیگر اثری ندارد؛ ادغام، کامیتِ ادغامِ &lt;code&gt;M&lt;/code&gt; را می‌سازد.&lt;/p&gt;
&lt;h2 id=&#34;روش-کار-در-یک-نگاه&#34;&gt;روش کار در یک نگاه&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;برنچ &lt;code&gt;main&lt;/code&gt; محلی را به‌روز کنید.&lt;/li&gt;
&lt;li&gt;یک برنچ فیچر بسازید.&lt;/li&gt;
&lt;li&gt;کارتان را در قدم‌های کوچک کامیت کنید.&lt;/li&gt;
&lt;li&gt;برنچ را پوش کنید و یک پول ریکوئست باز کنید.&lt;/li&gt;
&lt;li&gt;برنچ را با &lt;code&gt;main&lt;/code&gt; به‌روز نگه دارید.&lt;/li&gt;
&lt;li&gt;ادغام کنید و بعد برنچ را حذف کنید.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;بیایید قدم‌به‌قدم جلو برویم.&lt;/p&gt;
&lt;h2 id=&#34;قدم-۱-از-یک-main-بهروز-شروع-کنید&#34;&gt;قدم ۱: از یک main به‌روز شروع کنید&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;switch&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;pull&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;origin&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;git switch&lt;/code&gt; (گیت ۲.۲۳ به بعد) جایگزین مدرن‌تر و واضح‌ترِ &lt;code&gt;git checkout&lt;/code&gt; برای جابه‌جایی بین برنچ‌هاست.&lt;/p&gt;
&lt;h2 id=&#34;قدم-۲-یک-برنچ-فیچر-بسازید&#34;&gt;قدم ۲: یک برنچ فیچر بسازید&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;switch&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-c&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;feature/login-form&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;فلگ &lt;code&gt;-c&lt;/code&gt; برنچ را می‌سازد و یک‌جا به آن منتقل می‌شود. از نام‌های توصیفی با پیشوند استفاده کنید تا همه بفهمند هر برنچ برای چیست:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;پیشوند&lt;/th&gt;
&lt;th&gt;کاربرد&lt;/th&gt;
&lt;th&gt;مثال&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;feature/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;قابلیت جدید&lt;/td&gt;
&lt;td&gt;&lt;code&gt;feature/login-form&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fix/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;رفع باگ&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fix/password-reset-email&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;مستندات&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docs/api-examples&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;refactor/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;بهبود کد بدون تغییر رفتار&lt;/td&gt;
&lt;td&gt;&lt;code&gt;refactor/user-service&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;قدم-۳-در-قدمهای-کوچک-و-معنادار-کامیت-کنید&#34;&gt;قدم ۳: در قدم‌های کوچک و معنادار کامیت کنید&lt;/h2&gt;
&lt;p&gt;تغییری بدهید، مرورش کنید و بعد کامیت کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;status&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# what changed?&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;diff&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# review the exact changes&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;src/login.js&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# stage specific files&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;commit&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-m&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Add login form markup and validation&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;پیام کامیت را برای خودِ آینده‌تان بنویسید&lt;/p&gt;
&lt;p&gt;پیام را کوتاه و به شکل دستوری بنویسید (مثلاً &lt;em&gt;«Add validation»&lt;/em&gt;، نه &lt;em&gt;«Added validation»&lt;/em&gt;) و توضیح دهید &lt;strong&gt;چه چیزی&lt;/strong&gt; و &lt;strong&gt;چرا&lt;/strong&gt; تغییر کرده، نه اینکه چطور. یک آزمون خوب: پیامتان باید این جمله را کامل کند: &lt;em&gt;«If applied, this commit will…»&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;قدم-۴-پوش-کنید-و-پول-ریکوئست-باز-کنید&#34;&gt;قدم ۴: پوش کنید و پول ریکوئست باز کنید&lt;/h2&gt;
&lt;p&gt;اولین بار که برنچ جدیدی را پوش می‌کنید، به گیت بگویید کدام برنچِ ریموت را دنبال کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;push&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-u&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;origin&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;feature/login-form&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;-u&lt;/code&gt; برنچِ بالادستی (upstream) را تنظیم می‌کند تا از این به بعد یک &lt;code&gt;git push&lt;/code&gt; ساده کافی باشد. حالا در GitHub، GitLab یا Bitbucket پیشنهادی برای باز کردن یک &lt;strong&gt;پول ریکوئست&lt;/strong&gt; (در GitLab به آن &lt;em&gt;merge request&lt;/em&gt; می‌گویند) می‌بینید. این‌جا هم‌تیمی‌ها کدتان را بررسی می‌کنند، نظر می‌دهند و تست‌های خودکار پیش از رسیدن هر چیزی به &lt;code&gt;main&lt;/code&gt; اجرا می‌شوند.&lt;/p&gt;
&lt;h2 id=&#34;قدم-۵-برنچ-را-بهروز-نگه-دارید&#34;&gt;قدم ۵: برنچ را به‌روز نگه دارید&lt;/h2&gt;
&lt;p&gt;اگر در حین کار شما &lt;code&gt;main&lt;/code&gt; جلو رفت، آن تغییرات را به برنچتان بیاورید تا تداخل‌ها را زود و در تکه‌های کوچک حل کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;switch&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;pull&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;origin&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;switch&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;feature/login-form
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;merge&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;بعضی تیم‌ها به‌جای &lt;code&gt;git merge main&lt;/code&gt; از &lt;code&gt;git rebase main&lt;/code&gt; استفاده می‌کنند که کامیت‌های شما را روی آخرین نسخهٔ &lt;code&gt;main&lt;/code&gt; بازپخش می‌کند و تاریخچه‌ای خطی می‌سازد. هر دو روش درست‌اند؛ از قرارداد تیمتان پیروی کنید.&lt;/p&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;هرگز تاریخچهٔ مشترک را rebase نکنید&lt;/p&gt;
&lt;p&gt;rebase کامیت‌ها را بازنویسی می‌کند. فقط برنچ‌هایی را rebase کنید که هیچ‌کس دیگری کارش را روی آن‌ها بنا نکرده است؛ وگرنه برای هم‌تیمی‌هایتان تداخل‌های دردسرساز درست می‌کنید.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&#34;حل-کردن-تداخل-ادغام&#34;&gt;حل کردن تداخل ادغام&lt;/h3&gt;
&lt;p&gt;تداخل (conflict) وقتی پیش می‌آید که دو برنچ خط‌های یکسانی را تغییر داده باشند. گیت متوقف می‌شود و فایل را علامت‌گذاری می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
const MAX_ATTEMPTS = 5;
=======
const MAX_ATTEMPTS = 3;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; main&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;بخش &lt;code&gt;HEAD&lt;/code&gt; نسخهٔ برنچ شماست و بخش پایینی از &lt;code&gt;main&lt;/code&gt; می‌آید. فایل را طوری ویرایش کنید که نسخهٔ درست بماند، نشانه‌ها را پاک کنید و ادغام را تمام کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;add&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;src/config.js
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;commit&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;قدم-۶-ادغام-و-مرتبسازی&#34;&gt;قدم ۶: ادغام و مرتب‌سازی&lt;/h2&gt;
&lt;p&gt;وقتی پول ریکوئست تأیید شد، آن را از طریق پلتفرم میزبانی ادغام کنید. بعد محیط محلی را مرتب کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;switch&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;pull&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;origin&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;branch&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-d&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;feature/login-form&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;git branch -d&lt;/code&gt; از حذف برنچی که ادغام نشده خودداری می‌کند، پس گزینهٔ پیش‌فرض امنی است. اگر تیمتان از &lt;em&gt;squash merge&lt;/em&gt; استفاده می‌کند، ممکن است گیت برنچ را ادغام‌شده تشخیص ندهد. وقتی مطمئن شدید پول ریکوئست ادغام شده، &lt;code&gt;git branch -D&lt;/code&gt; حذف را اجباری می‌کند.&lt;/p&gt;
&lt;h2 id=&#34;دستورهای-کاربردی-برای-به-خاطر-سپردن&#34;&gt;دستورهای کاربردی برای به خاطر سپردن&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;branch&lt;span class=&#34;w&#34;&gt;                        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# list local branches&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;branch&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-a&lt;span class=&#34;w&#34;&gt;                     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# include remote branches&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;log&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--oneline&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--graph&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--all&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# visualise history&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;switch&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&lt;span class=&#34;w&#34;&gt;                      &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# jump back to the previous branch&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;stash&lt;span class=&#34;w&#34;&gt;                         &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# shelve uncommitted changes temporarily&lt;/span&gt;
git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;stash&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;pop&lt;span class=&#34;w&#34;&gt;                     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# bring them back&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;برنچ یک اشاره‌گر سبک است، پس آزادانه بسازیدش.&lt;/li&gt;
&lt;li&gt;یک برنچ برای هر فیچر یا رفع باگ، &lt;code&gt;main&lt;/code&gt; را همیشه آمادهٔ انتشار نگه می‌دارد.&lt;/li&gt;
&lt;li&gt;در قدم‌های کوچک کامیت کنید، پیام‌های واضح بنویسید و برای بررسی، پول ریکوئست باز کنید.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main&lt;/code&gt; را مرتب در برنچتان ادغام کنید تا از تداخل‌های بزرگ جلوگیری شود.&lt;/li&gt;
&lt;li&gt;بعد از ادغام، برنچ‌ها را حذف کنید تا مخزنتان مرتب بماند.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;این روش کار را حتی در پروژه‌های تک‌نفره هم به کار ببرید. عادت‌هایی می‌سازد که پیوستن به یک تیم را آسان می‌کند.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>نماد Big-O با کد واقعی</title>
      <link>https://cryo-networks.com/posts/big-o-notation-explained/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/big-o-notation-explained/</guid>
      <pubDate>Wed, 07 Oct 2026 09:00:00 +0000</pubDate>
      <category>الگوریتم‌ها</category>
      <description>پیچیدگی زمانی را بدون ترس از ریاضیات بفهمید. توابع واقعی پایتون را تحلیل می‌کنیم و می‌بینیم چرا کدِ O(n²) در مقیاس بزرگ از پا درمی‌آید.</description>
      <content:encoded>&lt;p&gt;کد شما روی ۱۰۰ آیتم کار می‌کند. آیا روی ۱٬۰۰۰٬۰۰۰ آیتم هم کار خواهد کرد؟ &lt;strong&gt;نماد Big-O&lt;/strong&gt; به همین سؤال جواب می‌دهد. این نماد توصیف می‌کند که زمان اجرا (یا مصرف حافظهٔ) یک الگوریتم با بزرگ‌تر شدن ورودی چطور &lt;em&gt;رشد&lt;/em&gt; می‌کند.&lt;/p&gt;
&lt;p&gt;برای استفاده از آن به ریاضیات پیشرفته نیازی ندارید. در این مقاله به توابع واقعی نگاه می‌کنیم، کاری را که انجام می‌دهند می‌شماریم و شهودی می‌سازیم که بتوانید روی کد خودتان به کار ببرید.&lt;/p&gt;
&lt;h2 id=&#34;ایده-اصلی-رشد-نه-سرعت&#34;&gt;ایدهٔ اصلی: رشد، نه سرعت&lt;/h2&gt;
&lt;p&gt;Big-O نمی‌گوید یک تابع ۳ میلی‌ثانیه طول می‌کشد. می‌گوید زمان چطور &lt;strong&gt;مقیاس می‌پذیرد&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;اگر ورودیِ یک تابع &lt;strong&gt;O(n)&lt;/strong&gt; را دو برابر کنید، زمان تقریباً دو برابر می‌شود.&lt;/li&gt;
&lt;li&gt;اگر ورودیِ یک تابع &lt;strong&gt;O(n²)&lt;/strong&gt; را دو برابر کنید، زمان تقریباً &lt;em&gt;چهار برابر&lt;/em&gt; می‌شود.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ثابت‌ها و جمله‌های کوچک‌تر را هم کنار می‌گذاریم. تابعی که &lt;code&gt;3n + 10&lt;/code&gt; گام برمی‌دارد همان &lt;strong&gt;O(n)&lt;/strong&gt; است، چون وقتی &lt;code&gt;n&lt;/code&gt; بزرگ می‌شود، &lt;code&gt;3&lt;/code&gt; و &lt;code&gt;10&lt;/code&gt; در مقایسه با خودِ رشد اهمیتی ندارند.&lt;/p&gt;
&lt;h2 id=&#34;o1-زمان-ثابت&#34;&gt;O(1): زمان ثابت&lt;/h2&gt;
&lt;p&gt;مقدار کار اصلاً به اندازهٔ ورودی بستگی ندارد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_first&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;is_even&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;دسترسی به یک خانهٔ لیست، جست‌وجوی یک کلید در دیکشنری و افزودن به انتهای لیست (به‌طور میانگین) همه O(1) هستند.&lt;/p&gt;
&lt;h2 id=&#34;on-زمان-خطی&#34;&gt;O(n): زمان خطی&lt;/h2&gt;
&lt;p&gt;مقدار کار به نسبت مستقیم با ورودی رشد می‌کند. یک بار پیمایش همهٔ آیتم‌ها مثال کلاسیک آن است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;find_max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numbers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;largest&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;numbers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;numbers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# runs n times&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;largest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;largest&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;largest&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;عملیات O(n)ِ پنهان را هم خوب است بشناسید: &lt;code&gt;x in some_list&lt;/code&gt;، &lt;code&gt;some_list.index(x)&lt;/code&gt;، &lt;code&gt;sum()&lt;/code&gt; و &lt;code&gt;max()&lt;/code&gt; همه کل لیست را پیمایش می‌کنند.&lt;/p&gt;
&lt;h2 id=&#34;on²-زمان-درجه-دو&#34;&gt;O(n²): زمان درجهٔ دو&lt;/h2&gt;
&lt;p&gt;حلقه‌ای داخل حلقهٔ دیگر که هر دو روی ورودی اجرا می‌شوند، تقریباً n × n گام به شما می‌دهد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;has_duplicates&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# nested loop&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;برای ۱٬۰۰۰ آیتم این حدود نیم میلیون مقایسه است. برای ۱٬۰۰۰٬۰۰۰ آیتم حدود &lt;strong&gt;۵۰۰ میلیارد&lt;/strong&gt;. این فاصلهٔ بین «فوری» و «فردا برگرد» است.&lt;/p&gt;
&lt;h2 id=&#34;راهحل-حافظه-را-با-سرعت-معاوضه-کنید&#34;&gt;راه‌حل: حافظه را با سرعت معاوضه کنید&lt;/h2&gt;
&lt;p&gt;می‌توانیم &lt;code&gt;has_duplicates&lt;/code&gt; را با به خاطر سپردنِ آیتم‌های دیده‌شده در یک &lt;strong&gt;set&lt;/strong&gt; به O(n) برسانیم؛ بررسی عضویت در set به‌طور میانگین O(1) است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;has_duplicates&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;seen&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# runs n times&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;seen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;        &lt;span class=&#34;c1&#34;&gt;# O(1) on average&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;seen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# O(1) on average&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;یا به شکل خلاصه‌تر:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;has_duplicates&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;کمی حافظهٔ اضافه (فضای O(n)) خرج می‌کنیم تا مقدار عظیمی زمان صرفه‌جویی کنیم. این معاوضه یکی از رایج‌ترین بهینه‌سازی‌ها در کدهای دنیای واقعی است.&lt;/p&gt;
&lt;h2 id=&#34;olog-n-زمان-لگاریتمی&#34;&gt;O(log n): زمان لگاریتمی&lt;/h2&gt;
&lt;p&gt;الگوریتم‌های لگاریتمی در هر گام مسئله را نصف می‌کنند. &lt;strong&gt;جست‌وجوی دودویی&lt;/strong&gt; (binary search) روی یک لیست مرتب، مثال درسیِ آن است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;binary_search&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sorted_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;low&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;high&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sorted_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;low&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;high&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;low&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;high&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sorted_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sorted_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;low&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;       &lt;span class=&#34;c1&#34;&gt;# discard the left half&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;high&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;# discard the right half&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;جست‌وجو در ۱٬۰۰۰٬۰۰۰ آیتم مرتب حداکثر حدود &lt;strong&gt;۲۰ گام&lt;/strong&gt; طول می‌کشد، چون ۲ به توان ۲۰ تقریباً ۱٬۰۰۰٬۰۰۰ است. داده را دو برابر کنید و فقط یک گام اضافه می‌شود.&lt;/p&gt;
&lt;h2 id=&#34;on-log-n-نقطه-طلایی-مرتبسازی&#34;&gt;O(n log n): نقطهٔ طلایی مرتب‌سازی&lt;/h2&gt;
&lt;p&gt;الگوریتم‌های مرتب‌سازیِ کارآمد و همه‌منظوره در &lt;strong&gt;O(n log n)&lt;/strong&gt; اجرا می‌شوند؛ از جمله merge sort و Timsort که پشتوانهٔ &lt;code&gt;sorted()&lt;/code&gt; و &lt;code&gt;list.sort()&lt;/code&gt; در پایتون است. این فقط کمی بدتر از خطی است و بهترین حالت ممکن برای مرتب‌سازی از طریق مقایسهٔ عناصر است.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;n&#34;&gt;names&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sorted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;names&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# O(n log n)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;مقایسه-نرخهای-رشد&#34;&gt;مقایسهٔ نرخ‌های رشد&lt;/h2&gt;
&lt;p&gt;تعداد تقریبی گام‌ها برای اندازه‌های مختلف ورودی:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;پیچیدگی&lt;/th&gt;
&lt;th&gt;n = 10&lt;/th&gt;
&lt;th&gt;n = 1,000&lt;/th&gt;
&lt;th&gt;n = 1,000,000&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;1,000,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O(n log n)&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;20,000,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O(n²)&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;1,000,000&lt;/td&gt;
&lt;td&gt;1,000,000,000,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;همان نرخ‌های رشد به شکل منحنی: با بزرگ شدن n فاصلهٔ آن‌ها به‌شدت زیاد می‌شود&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;یک قاعدهٔ سرانگشتی&lt;/p&gt;
&lt;p&gt;یک پردازندهٔ مدرن که کد کامپایل‌شده اجرا می‌کند، به‌طور خیلی تقریبی ۱۰ به توان ۸ عملیات ساده در ثانیه انجام می‌دهد و پایتون کمتر از این. اگر الگوریتم شما ۱۰ به توان ۱۲ گام لازم داشته باشد، هیچ ارتقای سخت‌افزاری نجاتتان نمی‌دهد. یک الگوریتم بهتر نجاتتان می‌دهد.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;چطور-کد-خودتان-را-تحلیل-کنید&#34;&gt;چطور کد خودتان را تحلیل کنید&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;حلقه‌ها را پیدا کنید.&lt;/strong&gt; حلقه‌ای روی ورودی معمولاً O(n) است. حلقه‌های تودرتو روی ورودی در هم ضرب می‌شوند: O(n²).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;داخل فراخوانی توابع را ببینید.&lt;/strong&gt; &lt;code&gt;item in my_list&lt;/code&gt; داخل یک حلقه، یک حلقهٔ تودرتوی پنهان است.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;بزرگ‌ترین جمله را نگه دارید.&lt;/strong&gt; O(n² + n) ساده می‌شود به O(n²).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;به بدترین حالت فکر کنید.&lt;/strong&gt; اگر چیز دیگری گفته نشده باشد، Big-O معمولاً بدترین حالت را توصیف می‌کند.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;یک مثال فریبنده. پیچیدگی‌اش چقدر است؟&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;common_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;اگر &lt;code&gt;b&lt;/code&gt; یک لیست باشد، &lt;code&gt;x in b&lt;/code&gt; هر بار آن را پیمایش می‌کند، پس این کد &lt;strong&gt;O(n × m)&lt;/strong&gt; است. اول &lt;code&gt;b&lt;/code&gt; را به set تبدیل کنید تا به &lt;strong&gt;O(n + m)&lt;/strong&gt; برسد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;common_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;b_set&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;                          &lt;span class=&#34;c1&#34;&gt;# O(m)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;     &lt;span class=&#34;c1&#34;&gt;# O(n)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Big-O توصیف می‌کند مقدار کار با اندازهٔ ورودی چطور &lt;strong&gt;رشد&lt;/strong&gt; می‌کند و ثابت‌ها را نادیده می‌گیرد.&lt;/li&gt;
&lt;li&gt;کلاس‌های رایج، از سریع به کند: &lt;code&gt;O(1)&lt;/code&gt;، &lt;code&gt;O(log n)&lt;/code&gt;، &lt;code&gt;O(n)&lt;/code&gt;، &lt;code&gt;O(n log n)&lt;/code&gt; و &lt;code&gt;O(n²)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;حلقه‌های تودرتو و پیمایش‌های پنهان (&lt;code&gt;in&lt;/code&gt; روی لیست) مقصرهای همیشگیِ کدهای کند هستند.&lt;/li&gt;
&lt;li&gt;set و دیکشنری جست‌وجوی O(n) را به O(1) تبدیل می‌کنند و این معمولاً ساده‌ترین بهبود بزرگ است.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;دفعهٔ بعد که کدتان با بزرگ شدن داده کند شد، اول سراغ سرور سریع‌تر نروید. سراغ Big-O بروید.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>Flexbox یا Grid در CSS: کدام را کِی استفاده کنیم</title>
      <link>https://cryo-networks.com/posts/css-flexbox-vs-grid/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/css-flexbox-vs-grid/</guid>
      <pubDate>Wed, 30 Sep 2026 09:00:00 +0000</pubDate>
      <category>CSS</category>
      <description>Flexbox و Grid هر دو عناصر را چیدمان می‌کنند، اما متفاوت فکر می‌کنند. قانون یک‌بعدی در برابر دوبعدی را یاد بگیرید و با هر کدام چیدمان‌های واقعی بسازید.</description>
      <content:encoded>&lt;p&gt;Flexbox و CSS Grid دو سیستم چیدمانِ مدرن در CSS هستند و مبتدی‌ها اغلب می‌پرسند کدام «بهتر» است. جواب صادقانه این است: هیچ‌کدام. آن‌ها مسئله‌های متفاوتی را حل می‌کنند و چیدمان‌های حرفه‌ای از هر دو استفاده می‌کنند، اغلب در یک صفحه.&lt;/p&gt;
&lt;h2 id=&#34;قانونی-که-باید-به-خاطر-بسپارید&#34;&gt;قانونی که باید به خاطر بسپارید&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Flexbox&lt;/strong&gt; چیزها را در &lt;strong&gt;یک بُعد&lt;/strong&gt; می‌چیند: یک سطر &lt;em&gt;یا&lt;/em&gt; یک ستون.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grid&lt;/strong&gt; چیزها را در &lt;strong&gt;دو بُعد&lt;/strong&gt; می‌چیند: سطرها &lt;em&gt;و&lt;/em&gt; ستون‌ها، هم‌زمان.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;به بیان دیگر: Flexbox &lt;strong&gt;محتوامحور&lt;/strong&gt; است؛ آیتم‌ها تعیین می‌کنند چقدر فضا لازم دارند و کانتینر فضای باقی‌مانده را تقسیم می‌کند. Grid &lt;strong&gt;چیدمان‌محور&lt;/strong&gt; است؛ شما ستون‌ها و سطرها را تعریف می‌کنید و بعد آیتم‌ها را در آن‌ها قرار می‌دهید.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;Flexbox آیتم‌ها را در امتداد یک محور توزیع می‌کند؛ Grid آن‌ها را هم‌زمان در سطرها و ستون‌ها تراز می‌کند&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&#34;مبانی-flexbox&#34;&gt;مبانی Flexbox&lt;/h2&gt;
&lt;p&gt;هر عنصری را با &lt;code&gt;display: flex&lt;/code&gt; به یک کانتینرِ فلکس تبدیل کنید. فرزندان مستقیمش به آیتم‌های فلکس تبدیل می‌شوند و در یک سطر کنار هم قرار می‌گیرند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;toolbar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;flex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;align-items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* alignment on the cross axis */&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;justify-content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;space-between&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* distribution on the main axis */&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;gap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;ویژگی‌هایی که ۹۰ درصد مواقع به کار می‌برید:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ویژگی&lt;/th&gt;
&lt;th&gt;کاری که انجام می‌دهد&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;flex-direction&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;row&lt;/code&gt; (پیش‌فرض) یا &lt;code&gt;column&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;justify-content&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;فضا را در امتداد محور اصلی تقسیم می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;align-items&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;آیتم‌ها را روی محور عرضی تراز می‌کند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;بین آیتم‌ها فاصله می‌گذارد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;flex-wrap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;اجازه می‌دهد آیتم‌ها به خط بعد بروند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;flex: 1&lt;/code&gt; (روی یک آیتم)&lt;/td&gt;
&lt;td&gt;آیتم بزرگ می‌شود تا فضای موجود را پر کند&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3 id=&#34;مثال-نوار-ناوبری&#34;&gt;مثال: نوار ناوبری&lt;/h3&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;nav&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;navbar&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;logo&amp;quot;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Brand&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ul&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;links&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;li&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;/docs&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Docs&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;li&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;li&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;/blog&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Blog&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;li&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;button&amp;quot;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;/signup&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Sign up&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;nav&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;navbar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;flex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;align-items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;gap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;links&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;flex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;gap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;margin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* the auto right margin pushes the button to the far right */&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;padding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;list-style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;none&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;ترفند margin خودکار&lt;/p&gt;
&lt;p&gt;در یک کانتینر فلکس، &lt;code&gt;margin-left: auto&lt;/code&gt; یا &lt;code&gt;margin-right: auto&lt;/code&gt; روی یک آیتم، تمام فضای خالیِ آن سمت را جذب می‌کند. این تمیزترین راه برای دور کردن یک آیتم از بقیه است.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&#34;مثال-وسطچین-کردن-کامل&#34;&gt;مثال: وسط‌چین کردن کامل&lt;/h3&gt;
&lt;p&gt;سؤال معروفِ «چطور یک div را وسط‌چین کنم؟» با Flexbox جواب کوتاهی دارد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;flex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;justify-content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;align-items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;با Grid هم &lt;code&gt;display: grid; place-items: center;&lt;/code&gt; همین کار را می‌کند.&lt;/p&gt;
&lt;h2 id=&#34;مبانی-grid&#34;&gt;مبانی Grid&lt;/h2&gt;
&lt;p&gt;Grid وقتی می‌درخشد که بخواهید آیتم‌ها در هر دو جهت تراز شوند. ستون‌ها (و در صورت نیاز سطرها) را روی کانتینر تعریف کنید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;gallery&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;repeat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;gap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;واحد &lt;code&gt;fr&lt;/code&gt; یعنی «یک سهم از فضای آزاد»، پس &lt;code&gt;repeat(3, 1fr)&lt;/code&gt; سه ستونِ هم‌اندازه می‌سازد.&lt;/p&gt;
&lt;h3 id=&#34;مثال-گرید-کارت-واکنشگرا-بدون-media-query&#34;&gt;مثال: گریدِ کارتِ واکنش‌گرا بدون media query&lt;/h3&gt;
&lt;p&gt;این یک خط ارزش حفظ کردن دارد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;cards&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;repeat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;-fill&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;minmax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;250&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;gap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;معنایش این است: &lt;em&gt;«هر تعداد ستونی که جا می‌شود بساز، هر کدام حداقل ۲۵۰ پیکسل، و آن‌ها را بکش تا سطر پر شود.»&lt;/em&gt; روی موبایل یک ستون می‌گیرید و روی یک مانیتور عریض شاید چهار ستون؛ بدون حتی یک media query.&lt;/p&gt;
&lt;h3 id=&#34;مثال-چیدمان-کامل-صفحه&#34;&gt;مثال: چیدمان کامل صفحه&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;grid-template-areas&lt;/code&gt; در Grid به شما اجازه می‌دهد چیدمانتان را به شکل متن بکشید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;240&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-template-rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fr&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-template-areas&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;header  header&amp;quot;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;sidebar main&amp;quot;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;footer  footer&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;min-height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;vh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-area&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;aside&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-area&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sidebar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-area&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;footer&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-area&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;footer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;media&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;max-width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;700px&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-template-rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fr&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-template-areas&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;header&amp;quot;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;main&amp;quot;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;sidebar&amp;quot;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;footer&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;دقت کنید که نسخهٔ موبایل فقط ناحیه‌ها را جابه‌جا می‌کند. HTML اصلاً تغییری نمی‌کند.&lt;/p&gt;
&lt;h2 id=&#34;مقایسه-کنار-هم&#34;&gt;مقایسهٔ کنار هم&lt;/h2&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Flexbox&lt;/th&gt;
&lt;th&gt;Grid&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ابعاد&lt;/td&gt;
&lt;td&gt;یک (سطر &lt;strong&gt;یا&lt;/strong&gt; ستون)&lt;/td&gt;
&lt;td&gt;دو (سطرها &lt;strong&gt;و&lt;/strong&gt; ستون‌ها)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;رویکرد&lt;/td&gt;
&lt;td&gt;محتوامحور&lt;/td&gt;
&lt;td&gt;چیدمان‌محور&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;بهترین کاربرد&lt;/td&gt;
&lt;td&gt;نوار ناوبری، نوار ابزار، گروه دکمه‌ها، وسط‌چینی&lt;/td&gt;
&lt;td&gt;چیدمان صفحه، گالری، داشبورد، فرم&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;اندازه‌دهی&lt;/td&gt;
&lt;td&gt;آیتم‌ها اندازهٔ خودشان را تعیین می‌کنند و بعد منعطف می‌شوند&lt;/td&gt;
&lt;td&gt;ستون‌ها و سطرها اندازه را تعیین می‌کنند و آیتم‌ها آن را پر می‌کنند&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;آیتم‌های هم‌پوشان&lt;/td&gt;
&lt;td&gt;دشوار&lt;/td&gt;
&lt;td&gt;آسان: آیتم‌ها را در یک خانه قرار دهید&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;استفاده-همزمان-از-هر-دو&#34;&gt;استفادهٔ هم‌زمان از هر دو&lt;/h2&gt;
&lt;p&gt;رابط‌های کاربری واقعی این دو را تودرتو به کار می‌برند. یک الگوی رایج: &lt;strong&gt;Grid برای ساختار کلی، Flexbox داخل هر کامپوننت&lt;/strong&gt;:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;c&#34;&gt;/* Grid arranges the cards */&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;cards&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;repeat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;-fill&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;minmax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;250&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;gap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;/* Flexbox arranges the content inside each card */&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;card&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;flex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;flex-direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;column&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;card&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;footer&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;margin-top&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;/* pins the footer to the bottom of every card */&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Grid همهٔ کارت‌های یک سطر را هم‌قد می‌کند و ترفند &lt;code&gt;margin-top: auto&lt;/code&gt; فوتر کارت‌ها را تراز نگه می‌دارد، حتی وقتی مقدار متن کارت‌ها متفاوت است. جزئیاتی کوچک که طراحی را حرفه‌ای نشان می‌دهد.&lt;/p&gt;
&lt;h2 id=&#34;راهنمای-سریع-تصمیمگیری&#34;&gt;راهنمای سریع تصمیم‌گیری&lt;/h2&gt;
&lt;p&gt;از خودتان بپرسید:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;آیتم‌ها را در یک خط می‌چینم؟&lt;/strong&gt; از Flexbox استفاده کنید.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;لازم است آیتم‌ها در سطرها &lt;em&gt;و&lt;/em&gt; ستون‌ها تراز شوند؟&lt;/strong&gt; از Grid استفاده کنید.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;محتوا باید اندازه را تعیین کند؟&lt;/strong&gt; از Flexbox استفاده کنید.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;چیدمان باید اندازه را تعیین کند؟&lt;/strong&gt; از Grid استفاده کنید.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;اگر مطمئن نیستید، برای کامپوننت‌های کوچک با Flexbox و برای هر چیزی که شبیه جدول، گالری یا اسکلت صفحه است با Grid شروع کنید.&lt;/p&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Flexbox یک‌بعدی و محتوامحور است و برای کامپوننت‌ها عالی است.&lt;/li&gt;
&lt;li&gt;Grid دوبعدی و چیدمان‌محور است و برای ساختار صفحه و گالری‌ها عالی است.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;repeat(auto-fill, minmax(…, 1fr))&lt;/code&gt; بدون media query گریدِ واکنش‌گرا به شما می‌دهد.&lt;/li&gt;
&lt;li&gt;آن‌ها را ترکیب کنید: Grid برای ساختار، Flexbox داخل اجزا.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ابزار DevTools مرورگرتان را روی هر وب‌سایت مدرنی باز کنید و چیدمان را بررسی کنید. همه‌جا این دو سیستم را در کنار هم پیدا می‌کنید.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>JOINها در SQL با مثال‌های ساده</title>
      <link>https://cryo-networks.com/posts/sql-joins-explained/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/sql-joins-explained/</guid>
      <pubDate>Wed, 23 Sep 2026 09:00:00 +0000</pubDate>
      <category>SQL</category>
      <description>JOINهای INNER، LEFT، RIGHT و FULL با دو جدول کوچک. دقیقاً ببینید هر نوع JOIN کدام ردیف‌ها را برمی‌گرداند و چرا.</description>
      <content:encoded>&lt;p&gt;پایگاه‌های دادهٔ رابطه‌ای برای جلوگیری از تکرار، داده‌ها را در جدول‌های جداگانه نگه می‌دارند: مشتریان در یک جدول و سفارش‌ها در جدولی دیگر. &lt;strong&gt;JOIN&lt;/strong&gt; راهی است برای کنار هم گذاشتن دوبارهٔ این داده‌ها هنگام کوئری گرفتن.&lt;/p&gt;
&lt;p&gt;بهترین راه برای فهمیدن JOINها این است که کارشان را روی ردیف‌های واقعی ببینید. در تمام این راهنما از دو جدول کوچک استفاده می‌کنیم.&lt;/p&gt;
&lt;h2 id=&#34;جدولهای-نمونه&#34;&gt;جدول‌های نمونه&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;customers&lt;/strong&gt; (مشتریان)&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Ada&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Grace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Linus&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;orders&lt;/strong&gt; (سفارش‌ها)&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;customer_id&lt;/th&gt;
&lt;th&gt;total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;49.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;15.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;103&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;99.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;104&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;25.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;به دو نکته دقت کنید: &lt;strong&gt;Linus هیچ سفارشی ندارد&lt;/strong&gt; و &lt;strong&gt;سفارش ۱۰۴ متعلق به مشتری ۴ است که وجود ندارد&lt;/strong&gt; (شاید حسابش حذف شده). دقیقاً در همین موارد مرزی است که JOINهای مختلف رفتار متفاوتی دارند.&lt;/p&gt;
&lt;p&gt;می‌خواهید همراه ما امتحان کنید؟ این SQLِ آماده‌سازی است که در SQLite، PostgreSQL و MySQL کار می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;INTEGER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;PRIMARY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;TEXT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;INTEGER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;PRIMARY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;INTEGER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;DECIMAL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;INSERT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INTO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;VALUES&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Ada&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Grace&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Linus&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;INSERT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INTO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;VALUES&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;101&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;49&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;102&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;103&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;104&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;پایگاه داده بدون &lt;code&gt;ORDER BY&lt;/code&gt; ترتیب ردیف‌ها را تضمین نمی‌کند، پس نتایج زیر برای خوانایی مرتب شده‌اند.&lt;/p&gt;
&lt;h2 id=&#34;inner-join-فقط-ردیفهای-منطبق&#34;&gt;INNER JOIN: فقط ردیف‌های منطبق&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;INNER JOIN&lt;/code&gt; ردیف‌هایی را برمی‌گرداند که شرطِ JOIN در &lt;strong&gt;هر دو&lt;/strong&gt; جدول برقرار باشد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;order_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;INNER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;JOIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;order_id&lt;/th&gt;
&lt;th&gt;total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ada&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;49.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ada&lt;/td&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;15.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grace&lt;/td&gt;
&lt;td&gt;103&lt;/td&gt;
&lt;td&gt;99.99&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Linus حذف می‌شود چون سفارشی ندارد و سفارش ۱۰۴ هم حذف می‌شود چون مشتری ندارد. نوشتن &lt;code&gt;JOIN&lt;/code&gt; به‌تنهایی یعنی &lt;code&gt;INNER JOIN&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;left-join-همه-ردیفهای-جدول-چپ&#34;&gt;LEFT JOIN: همهٔ ردیف‌های جدول چپ&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;LEFT JOIN&lt;/code&gt; &lt;strong&gt;همهٔ ردیف‌های جدول چپ&lt;/strong&gt; (جدولِ بعد از &lt;code&gt;FROM&lt;/code&gt;) را نگه می‌دارد و هر جا در سمت راست تطابقی نباشد، &lt;code&gt;NULL&lt;/code&gt; می‌گذارد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;order_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;LEFT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;JOIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;order_id&lt;/th&gt;
&lt;th&gt;total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ada&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;49.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ada&lt;/td&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;15.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grace&lt;/td&gt;
&lt;td&gt;103&lt;/td&gt;
&lt;td&gt;99.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linus&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Linus برگشته و ستون‌های سفارشش &lt;code&gt;NULL&lt;/code&gt; است. بعد از &lt;code&gt;INNER JOIN&lt;/code&gt;، این پرکاربردترین JOIN است.&lt;/p&gt;
&lt;h3 id=&#34;پیدا-کردن-ردیفهای-بیتطابق&#34;&gt;پیدا کردن ردیف‌های بی‌تطابق&lt;/h3&gt;
&lt;p&gt;یک ترفند کلاسیک: ترکیب &lt;code&gt;LEFT JOIN&lt;/code&gt; با &lt;code&gt;WHERE ... IS NULL&lt;/code&gt; برای پیدا کردن «یتیم‌ها». این‌جا مشتریانی را پیدا می‌کنیم که هرگز سفارش نداده‌اند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;LEFT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;JOIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;IS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;نتیجه: &lt;strong&gt;Linus&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&#34;right-join-همه-ردیفهای-جدول-راست&#34;&gt;RIGHT JOIN: همهٔ ردیف‌های جدول راست&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;RIGHT JOIN&lt;/code&gt; قرینهٔ آن است: همهٔ ردیف‌های جدول &lt;strong&gt;راست&lt;/strong&gt; را نگه می‌دارد.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;order_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;RIGHT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;JOIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;order_id&lt;/th&gt;
&lt;th&gt;total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ada&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;49.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ada&lt;/td&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;15.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grace&lt;/td&gt;
&lt;td&gt;103&lt;/td&gt;
&lt;td&gt;99.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;104&lt;/td&gt;
&lt;td&gt;25.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;حالا سفارشِ یتیمِ ۱۰۴ بدون نام مشتری ظاهر می‌شود. در عمل، بیشتر برنامه‌نویسان RIGHT JOIN را با جابه‌جا کردن ترتیب جدول‌ها به LEFT JOIN تبدیل می‌کنند. کوئری وقتی خواناتر است که جدولِ «همه را نگه دار» همیشه اول بیاید.&lt;/p&gt;
&lt;h2 id=&#34;full-outer-join-همهچیز-از-هر-دو&#34;&gt;FULL OUTER JOIN: همه‌چیز از هر دو&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;FULL OUTER JOIN&lt;/code&gt; همهٔ ردیف‌های هر دو جدول را نگه می‌دارد و هر جا بتواند آن‌ها را تطبیق می‌دهد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;order_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;OUTER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;JOIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;order_id&lt;/th&gt;
&lt;th&gt;total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ada&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;49.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ada&lt;/td&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;15.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grace&lt;/td&gt;
&lt;td&gt;103&lt;/td&gt;
&lt;td&gt;99.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linus&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;104&lt;/td&gt;
&lt;td&gt;25.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;برای تطبیق داده‌ها کاربردی است: مقایسهٔ دو فهرست و پیدا کردن چیزهایی که در هر طرف کم است.&lt;/p&gt;
&lt;div class=&#34;admonition note&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;پشتیبانی پایگاه‌های داده&lt;/p&gt;
&lt;p&gt;MySQL از &lt;code&gt;FULL OUTER JOIN&lt;/code&gt; پشتیبانی نمی‌کند؛ می‌توانید آن را با ترکیب یک &lt;code&gt;LEFT JOIN&lt;/code&gt; و یک &lt;code&gt;RIGHT JOIN&lt;/code&gt; به کمک &lt;code&gt;UNION&lt;/code&gt; شبیه‌سازی کنید. SQLite از نسخهٔ ۳.۳۹.۰ به بعد از &lt;code&gt;RIGHT&lt;/code&gt; و &lt;code&gt;FULL&lt;/code&gt; پشتیبانی می‌کند.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;جدول-خلاصه&#34;&gt;جدول خلاصه&lt;/h2&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;هر JOIN کدام ردیف‌ها را نگه می‌دارد، به شکل نمودار ون&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;JOIN&lt;/th&gt;
&lt;th&gt;ردیف‌های بی‌تطابق را از کجا نگه می‌دارد&lt;/th&gt;
&lt;th&gt;کاربرد معمول&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INNER JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;هیچ‌کدام&lt;/td&gt;
&lt;td&gt;داده‌ای که باید در هر دو طرف وجود داشته باشد&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LEFT JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;جدول چپ&lt;/td&gt;
&lt;td&gt;«همهٔ مشتریان، به‌علاوهٔ سفارش‌هایشان در صورت وجود»&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RIGHT JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;جدول راست&lt;/td&gt;
&lt;td&gt;به‌ندرت؛ معمولاً به LEFT JOIN تبدیل می‌شود&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FULL OUTER JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;هر دو جدول&lt;/td&gt;
&lt;td&gt;تطبیق دو مجموعه داده&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;تجمیع-بعد-از-join&#34;&gt;تجمیع بعد از JOIN&lt;/h2&gt;
&lt;p&gt;JOINها همراه با &lt;code&gt;GROUP BY&lt;/code&gt; واقعاً قدرتمند می‌شوند. این‌جا تعداد سفارش و مجموع خرید هر مشتری را می‌بینیم، از جمله مشتریانی که هیچ سفارشی ندارند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;               &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;order_count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;COALESCE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SUM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_spent&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;LEFT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;JOIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orders&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ON&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;GROUP&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;ORDER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_spent&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DESC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;order_count&lt;/th&gt;
&lt;th&gt;total_spent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Grace&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;99.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ada&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;64.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linus&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;تفاوت COUNT(column) و COUNT(*)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;COUNT(o.id)&lt;/code&gt; فقط مقدارهای غیر NULL را می‌شمارد، پس Linus به‌درستی &lt;code&gt;0&lt;/code&gt; می‌گیرد. &lt;code&gt;COUNT(*)&lt;/code&gt; ردیف‌ها را می‌شمارد و برای Linus عدد &lt;code&gt;1&lt;/code&gt; را می‌داد، چون LEFT JOIN همچنان یک ردیف برای او تولید می‌کند.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;اشتباههای-رایج&#34;&gt;اشتباه‌های رایج&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;فیلتر کردن جدول راست در &lt;code&gt;WHERE&lt;/code&gt; بعد از &lt;code&gt;LEFT JOIN&lt;/code&gt;.&lt;/strong&gt; شرطی مثل &lt;code&gt;WHERE o.total &amp;gt; 20&lt;/code&gt; بی‌سروصدا ردیف‌های &lt;code&gt;NULL&lt;/code&gt; را حذف می‌کند و LEFT JOIN شما را به INNER JOIN تبدیل می‌کند. شرط را به بخش &lt;code&gt;ON&lt;/code&gt; منتقل کنید: &lt;code&gt;LEFT JOIN orders AS o ON o.customer_id = c.id AND o.total &amp;gt; 20&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;استفاده از شرط JOIN اشتباه.&lt;/strong&gt; JOIN روی ستون‌های اشتباه یا بدون شرط واقعی می‌تواند یک &lt;em&gt;ضرب دکارتی&lt;/em&gt; بسازد: هر ردیف با تک‌تک ردیف‌های دیگر جفت می‌شود.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JOIN روی ستون‌هایی با نوع دادهٔ متفاوت.&lt;/strong&gt; این کار می‌تواند مانع استفادهٔ پایگاه داده از ایندکس‌ها شود و کوئری را کند کند.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;INNER JOIN&lt;/strong&gt; فقط ردیف‌هایی را برمی‌گرداند که در هر دو طرف منطبق باشند.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LEFT JOIN&lt;/strong&gt; همهٔ ردیف‌های جدول چپ را برمی‌گرداند و هر جا تطابقی نباشد &lt;code&gt;NULL&lt;/code&gt; می‌گذارد.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RIGHT JOIN&lt;/strong&gt; قرینهٔ LEFT است و معمولاً به LEFT JOIN بازنویسی می‌شود.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FULL OUTER JOIN&lt;/strong&gt; همه‌چیز را از هر دو جدول برمی‌گرداند.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LEFT JOIN ... WHERE right.id IS NULL&lt;/code&gt; ردیف‌های بی‌تطابق را پیدا می‌کند.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;دو جدول بالا را در SQLite (&lt;code&gt;sqlite3 shop.db&lt;/code&gt;) بسازید و هر کوئری را خودتان اجرا کنید. پنج دقیقه آزمایش از یک ساعت خواندن بهتر است.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>دستورهای ضروری لینوکس که هر برنامه‌نویسی باید بداند</title>
      <link>https://cryo-networks.com/posts/linux-command-line-essentials/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/linux-command-line-essentials/</guid>
      <pubDate>Wed, 16 Sep 2026 09:00:00 +0000</pubDate>
      <category>لینوکس</category>
      <description>با اطمینان در سیستم لینوکس جابه‌جا شوید، جست‌وجو کنید، بررسی کنید و آن را مدیریت کنید. گشتی کاربردی در دستورهایی که برنامه‌نویسان هر روز از آن‌ها استفاده می‌کنند.</description>
      <content:encoded>&lt;p&gt;چه روی یک سرور ابری دیپلوی کنید، چه داخل Docker کار کنید و چه فقط از ترمینالِ مک‌تان استفاده کنید، دیر یا زود دستورهای لینوکس را تایپ خواهید کرد. خبر خوب این است که چند ده دستور بیشترِ کارهای روزانه را پوشش می‌دهند.&lt;/p&gt;
&lt;p&gt;هر بخش در ادامه دستورها، گزینه‌هایی که واقعاً به کار می‌برید و مثال‌هایی از دنیای واقعی را نشان می‌دهد.&lt;/p&gt;
&lt;h2 id=&#34;جابهجایی-در-سیستم-فایل&#34;&gt;جابه‌جایی در سیستم فایل&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nb&#34;&gt;pwd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                 &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# where am I?&lt;/span&gt;
ls&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-lah&lt;span class=&#34;w&#34;&gt;             &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# list everything: long format, hidden files, human-readable sizes&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/var/log&lt;span class=&#34;w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# go to an absolute path&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;..&lt;span class=&#34;w&#34;&gt;               &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# up one level&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# jump back to the previous directory&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# go home (same as cd ~)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;تکمیل خودکار با Tab ساعت‌ها صرفه‌جویی می‌کند&lt;/p&gt;
&lt;p&gt;چند حرف اول نام یک فایل یا پوشه را تایپ کنید و &lt;kbd&gt;Tab&lt;/kbd&gt; را بزنید. شل آن را برایتان کامل می‌کند یا اگر بیش از یک گزینه وجود داشته باشد، گزینه‌ها را نشان می‌دهد.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;ساختن-کپی-جابهجایی-و-حذف&#34;&gt;ساختن، کپی، جابه‌جایی و حذف&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;mkdir&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;projects/blog/src&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# create nested directories in one go&lt;/span&gt;
touch&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;notes.txt&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# create an empty file (or update its timestamp)&lt;/span&gt;
cp&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;config.yml&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;config.yml.bak&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# copy a file&lt;/span&gt;
cp&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-r&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;src/&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;backup/&lt;span class=&#34;w&#34;&gt;             &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# copy a directory recursively&lt;/span&gt;
mv&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;draft.md&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;posts/final.md&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# move and/or rename&lt;/span&gt;
rm&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;old.log&lt;span class=&#34;w&#34;&gt;                     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# delete a file&lt;/span&gt;
rm&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-r&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build/&lt;span class=&#34;w&#34;&gt;                   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# delete a directory and everything in it&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition danger&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;سطل بازیافتی در کار نیست&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rm&lt;/code&gt; فوراً و برای همیشه حذف می‌کند. پیش از اجرای &lt;code&gt;rm -r&lt;/code&gt; مسیرها را دوباره بررسی کنید، مخصوصاً با wildcardها یا &lt;code&gt;sudo&lt;/code&gt;. افزودن &lt;code&gt;-i&lt;/code&gt; باعث می‌شود &lt;code&gt;rm&lt;/code&gt; پیش از هر حذف از شما بپرسد.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;خواندن-فایلها&#34;&gt;خواندن فایل‌ها&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;cat&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;package.json&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# print a whole (short) file&lt;/span&gt;
less&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/var/log/syslog&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# scroll through a long file (q to quit, / to search)&lt;/span&gt;
head&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-n&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;app.log&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# first 20 lines&lt;/span&gt;
tail&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-n&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;app.log&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# last 50 lines&lt;/span&gt;
tail&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-f&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;app.log&lt;span class=&#34;w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# follow new lines as they&amp;#39;re written, great for live logs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;جستوجو-داخل-فایلها-با-grep&#34;&gt;جست‌وجو داخل فایل‌ها با grep&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;grep&lt;/code&gt; خط‌هایی را پیدا می‌کند که با یک الگو مطابقت دارند. یکی از مفیدترین ابزارهایی است که یاد خواهید گرفت:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;grep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;ERROR&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;app.log&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# lines containing ERROR&lt;/span&gt;
grep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-i&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;timeout&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;app.log&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# case-insensitive&lt;/span&gt;
grep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-rn&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;TODO&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;src/&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# search recursively, show line numbers&lt;/span&gt;
grep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-v&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;DEBUG&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;app.log&lt;span class=&#34;w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# lines that do NOT match&lt;/span&gt;
grep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-c&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;404&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;access.log&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# count matching lines&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;پیدا-کردن-فایلها-با-find&#34;&gt;پیدا کردن فایل‌ها با find&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;find&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;.&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-name&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;*.py&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                       &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# all Python files below the current directory&lt;/span&gt;
find&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/var/log&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-name&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;*.log&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-mtime&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-1&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# .log files modified in the last 24 hours&lt;/span&gt;
find&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;.&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-type&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;f&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-size&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;+100M&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# files bigger than 100 MB&lt;/span&gt;
find&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;.&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-type&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;d&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-name&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;node_modules&lt;span class=&#34;w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# directories named node_modules&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;پایپ-و-تغییر-مسیر-ترکیب-دستورها&#34;&gt;پایپ و تغییر مسیر: ترکیب دستورها&lt;/h2&gt;
&lt;p&gt;قدرت واقعی خط فرمان از زنجیر کردن ابزارهای کوچک به هم می‌آید. پایپ &lt;code&gt;|&lt;/code&gt; خروجیِ یک دستور را به ورودیِ دستور بعدی می‌فرستد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;c1&#34;&gt;# Top 5 IP addresses hitting your web server&lt;/span&gt;
cut&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-d&lt;span class=&#34;s1&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-f1&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;access.log&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;sort&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;uniq&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-c&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;sort&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-rn&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;head&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-5&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;آن را از چپ به راست بخوانید: فیلد اول (آدرس IP) هر خط را بردار، آدرس‌ها را مرتب کن، تکراری‌ها را بشمار، بر اساس تعداد از بیشترین مرتب کن و پنج مورد اول را نشان بده.&lt;/p&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;هر دستور داده را تغییر می‌دهد و از طریق پایپ به دستور بعدی می‌فرستد&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;تغییر مسیر (redirection) خروجی را به فایل‌ها می‌فرستد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;ls&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-la&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;files.txt&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# write output to a file (overwrites it)&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;done&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build.log&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# append to a file&lt;/span&gt;
npm&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;test.log&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&amp;gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# capture both normal output and errors&lt;/span&gt;
wc&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-l&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&amp;lt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;data.csv&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# use a file as input: counts its lines&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;مجوزها-با-chmod-و-chown&#34;&gt;مجوزها با chmod و chown&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ls -l&lt;/code&gt; را اجرا کنید تا خط‌هایی شبیه این ببینید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;-rwxr-xr-- 1 deploy www-data 2048 Oct 12 09:30 deploy.sh&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;رشتهٔ مجوزها به سه گروه سه‌تایی تقسیم می‌شود: &lt;strong&gt;مالک&lt;/strong&gt; (&lt;code&gt;rwx&lt;/code&gt;)، &lt;strong&gt;گروه&lt;/strong&gt; (&lt;code&gt;r-x&lt;/code&gt;) و &lt;strong&gt;بقیه&lt;/strong&gt; (&lt;code&gt;r--&lt;/code&gt;). این‌جا &lt;code&gt;r&lt;/code&gt; یعنی خواندن، &lt;code&gt;w&lt;/code&gt; یعنی نوشتن و &lt;code&gt;x&lt;/code&gt; یعنی اجرا.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;chmod&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;+x&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;deploy.sh&lt;span class=&#34;w&#34;&gt;                              &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# make a script executable&lt;/span&gt;
chmod&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;644&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;index.html&lt;span class=&#34;w&#34;&gt;                            &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# owner: read/write, everyone else: read-only&lt;/span&gt;
chmod&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;755&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;scripts/&lt;span class=&#34;w&#34;&gt;                              &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# owner: full access, everyone else: read and enter&lt;/span&gt;
sudo&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;chown&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-R&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;www-data:www-data&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/var/www/site&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# change owner and group recursively&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;حالت‌های عددی با هم جمع می‌شوند: خواندن = ۴، نوشتن = ۲ و اجرا = ۱. پس &lt;code&gt;7&lt;/code&gt; یعنی ۴+۲+۱ (&lt;code&gt;rwx&lt;/code&gt;)، &lt;code&gt;5&lt;/code&gt; یعنی ۴+۱ (&lt;code&gt;r-x&lt;/code&gt;) و &lt;code&gt;4&lt;/code&gt; یعنی فقط خواندن.&lt;/p&gt;
&lt;h2 id=&#34;فرایندها-چه-چیزی-در-حال-اجراست&#34;&gt;فرایندها: چه چیزی در حال اجراست؟&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;ps&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;aux&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;grep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;node&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# find running node processes&lt;/span&gt;
top&lt;span class=&#34;w&#34;&gt;                         &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# live view of CPU and memory use (q to quit)&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;kill&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;12345&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# politely ask process 12345 to stop&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;kill&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-9&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;12345&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;               &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# force it to stop (last resort)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;بسیاری از سیستم‌ها &lt;code&gt;htop&lt;/code&gt; را هم دارند؛ جایگزینی خوش‌دست‌تر و رنگی برای &lt;code&gt;top&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;دیسک-و-حافظه&#34;&gt;دیسک و حافظه&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;df&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-h&lt;span class=&#34;w&#34;&gt;               &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# free disk space per filesystem&lt;/span&gt;
du&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-sh&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;*&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# size of each item in the current directory&lt;/span&gt;
du&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-sh&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;*&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;sort&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-h&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# ...sorted from smallest to largest&lt;/span&gt;
free&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-h&lt;span class=&#34;w&#34;&gt;             &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# memory usage&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;مبانی-شبکه&#34;&gt;مبانی شبکه&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;curl&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;https://example.com&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# fetch a page&lt;/span&gt;
curl&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-I&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;https://example.com&lt;span class=&#34;w&#34;&gt;       &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# headers only: check status codes and caching&lt;/span&gt;
curl&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-X&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;POST&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-H&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Content-Type: application/json&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt;
&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;-d&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;{&amp;quot;name&amp;quot;: &amp;quot;Ada&amp;quot;}&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;https://httpbin.org/post
sudo&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;ss&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-tlnp&lt;span class=&#34;w&#34;&gt;                     &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# which programs are listening on which ports&lt;/span&gt;
ping&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-c&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;example.com&lt;span class=&#34;w&#34;&gt;             &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# is the host reachable?&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;کار-روی-سرورهای-راه-دور&#34;&gt;کار روی سرورهای راه دور&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;ssh&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;user@203.0.113.10&lt;span class=&#34;w&#34;&gt;                                 &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# log in to a server&lt;/span&gt;
scp&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;report.pdf&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;user@203.0.113.10:~/&lt;span class=&#34;w&#34;&gt;                   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# copy a file to it&lt;/span&gt;
rsync&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-avz&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;./site/&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;user@203.0.113.10:/var/www/site/&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# sync a whole directory efficiently&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;گرفتن-راهنما&#34;&gt;گرفتن راهنما&lt;/h2&gt;
&lt;p&gt;لازم نیست همهٔ گزینه‌ها را حفظ کنید، چون سیستم خودش را مستند کرده است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;man&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;grep&lt;span class=&#34;w&#34;&gt;                 &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# the full manual (q to quit)&lt;/span&gt;
grep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--help&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# a quick summary of options&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;history&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;grep&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;docker&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# find that command you ran last week&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;و بهترین میان‌بُر: &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;R&lt;/kbd&gt; را بزنید و شروع به تایپ کنید تا تاریخچهٔ دستورهایتان را به‌صورت تعاملی جست‌وجو کنید.&lt;/p&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;کار&lt;/th&gt;
&lt;th&gt;دستورها&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;جابه‌جایی&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pwd&lt;/code&gt;، &lt;code&gt;ls&lt;/code&gt;، &lt;code&gt;cd&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;مدیریت فایل&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mkdir&lt;/code&gt;، &lt;code&gt;touch&lt;/code&gt;، &lt;code&gt;cp&lt;/code&gt;، &lt;code&gt;mv&lt;/code&gt;، &lt;code&gt;rm&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;خواندن فایل&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cat&lt;/code&gt;، &lt;code&gt;less&lt;/code&gt;، &lt;code&gt;head&lt;/code&gt;، &lt;code&gt;tail -f&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;جست‌وجو&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grep&lt;/code&gt;، &lt;code&gt;find&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ترکیب&lt;/td&gt;
&lt;td&gt;پایپ، &lt;code&gt;&amp;gt;&lt;/code&gt;، &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;، &lt;code&gt;2&amp;gt;&amp;amp;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;مجوزها&lt;/td&gt;
&lt;td&gt;&lt;code&gt;chmod&lt;/code&gt;، &lt;code&gt;chown&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;سیستم&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ps&lt;/code&gt;، &lt;code&gt;top&lt;/code&gt;، &lt;code&gt;kill&lt;/code&gt;، &lt;code&gt;df&lt;/code&gt;، &lt;code&gt;du&lt;/code&gt;، &lt;code&gt;free&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;شبکه&lt;/td&gt;
&lt;td&gt;&lt;code&gt;curl&lt;/code&gt;، &lt;code&gt;ss&lt;/code&gt;، &lt;code&gt;ssh&lt;/code&gt;، &lt;code&gt;rsync&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;یک ترمینال باز کنید و همان‌طور که می‌خوانید هر دستور را امتحان کنید. هدف اصلی، حافظهٔ عضلانی است و ظرف یک هفته تعجب خواهید کرد که چطور قبلاً بدون این دستورها کار می‌کردید.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>دکوریتورها در پایتون، قدم‌به‌قدم</title>
      <link>https://cryo-networks.com/posts/python-decorators-explained/</link>
      <guid isPermaLink="true">https://cryo-networks.com/posts/python-decorators-explained/</guid>
      <pubDate>Wed, 09 Sep 2026 09:00:00 +0000</pubDate>
      <category>پایتون</category>
      <description>دکوریتورها جادویی به نظر می‌رسند، اما فقط توابعی هستند که توابع دیگر را می‌پوشانند. دکوریتورهای زمان‌سنجی و تلاش مجدد را از صفر بسازید.</description>
      <content:encoded>&lt;p&gt;احتمالاً کدی شبیه این را در Flask، FastAPI یا Django دیده‌اید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nd&#34;&gt;@app&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;route&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;home&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;Hello!&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;آن خطی که با &lt;code&gt;@&lt;/code&gt; شروع می‌شود یک &lt;strong&gt;دکوریتور&lt;/strong&gt; (decorator) است. دکوریتورها به شما اجازه می‌دهند بدون تغییر کدِ یک تابع، رفتاری به آن اضافه کنید؛ مثل لاگ گرفتن، زمان‌سنجی، کش کردن یا کنترل دسترسی. شاید جادویی به نظر برسند، اما از سه ایدهٔ ساده ساخته شده‌اند. بیایید یکی‌یکی سراغشان برویم.&lt;/p&gt;
&lt;h2 id=&#34;ایده-۱-توابع-شیء-هستند&#34;&gt;ایدهٔ ۱: توابع شیء هستند&lt;/h2&gt;
&lt;p&gt;در پایتون، توابع هم مثل هر مقدار دیگری هستند. می‌توانید آن‌ها را به متغیرها نسبت دهید و به توابع دیگر بفرستید:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;greet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Hello, &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;!&amp;quot;&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;say_hello&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;greet&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# no parentheses: we&amp;#39;re not calling it&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;say_hello&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;# Hello, Ada!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;ایده-۲-میتوان-تابع-را-داخل-تابع-تعریف-کرد&#34;&gt;ایدهٔ ۲: می‌توان تابع را داخل تابع تعریف کرد&lt;/h2&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;outer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;inner&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;I&amp;#39;m inside!&amp;quot;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inner&lt;/span&gt;           &lt;span class=&#34;c1&#34;&gt;# return the function itself&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;outer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;                &lt;span class=&#34;c1&#34;&gt;# I&amp;#39;m inside!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;ایده-۳-توابع-داخلی-محیط-اطرافشان-را-به-خاطر-میسپارند&#34;&gt;ایدهٔ ۳: توابع داخلی محیط اطرافشان را به خاطر می‌سپارند&lt;/h2&gt;
&lt;p&gt;یک تابع داخلی می‌تواند از متغیرهای تابعی که آن را ساخته استفاده کند، حتی بعد از اینکه آن تابع بیرونی تمام شده باشد. به این &lt;strong&gt;کلوژر&lt;/strong&gt; (closure) می‌گویند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;make_multiplier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;factor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;multiply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;factor&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# &amp;quot;remembers&amp;quot; factor&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;multiply&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;double&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make_multiplier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;triple&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make_multiplier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;double&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;triple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# 10 15&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&#34;کنار-هم-گذاشتن-اولین-دکوریتور-شما&#34;&gt;کنار هم گذاشتن: اولین دکوریتور شما&lt;/h2&gt;
&lt;p&gt;دکوریتور تابعی است که &lt;strong&gt;یک تابع می‌گیرد و یک تابع جدید برمی‌گرداند&lt;/strong&gt;؛ معمولاً تابعی که تابع اصلی را با رفتاری اضافه می‌پوشاند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;upper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wrapper&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;greet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Hello, &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;!&amp;quot;&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;greet&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;shout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;greet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;       &lt;span class=&#34;c1&#34;&gt;# wrap it manually&lt;/span&gt;
&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;greet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;        &lt;span class=&#34;c1&#34;&gt;# HELLO, ADA!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;سینتکس &lt;code&gt;@&lt;/code&gt; فقط میان‌بُری برای همان خطِ &lt;code&gt;greet = shout(greet)&lt;/code&gt; است:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nd&#34;&gt;@shout&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;greet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Hello, &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;!&amp;quot;&lt;/span&gt;

&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;greet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;        &lt;span class=&#34;c1&#34;&gt;# HELLO, ADA!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&#34;diagram&#34;&gt;&lt;figcaption&gt;خط @ واقعاً چه می‌کند: دکوریتور تابع شما را می‌گیرد و جایگزینی برایش برمی‌گرداند&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;*args&lt;/code&gt; و &lt;code&gt;**kwargs&lt;/code&gt; به wrapper اجازه می‌دهند هر آرگومانی را بپذیرد و مستقیم پاس بدهد، پس دکوریتور روی توابعی با هر امضایی کار می‌کند.&lt;/p&gt;
&lt;h2 id=&#34;functoolswraps-را-فراموش-نکنید&#34;&gt;functools.wraps را فراموش نکنید&lt;/h2&gt;
&lt;p&gt;دکوریتور ما یک مشکل ظریف دارد: تابعِ پوشانده‌شده هویتش را از دست داده است.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;greet&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;# wrapper&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;این مشکل دیباگ کردن، ابزارهای مستندسازی و بعضی فریم‌ورک‌ها را خراب می‌کند. با &lt;code&gt;functools.wraps&lt;/code&gt; درستش کنید؛ این تابع نام، docstring و دیگر اطلاعات تابع اصلی را روی wrapper کپی می‌کند:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;functools&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wraps&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;nd&#34;&gt;@wraps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;upper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wrapper&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&#34;admonition tip&#34;&gt;
&lt;p class=&#34;admonition-title&#34;&gt;عادتش کنید&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@wraps(func)&lt;/code&gt; را به هر دکوریتوری که می‌نویسید اضافه کنید. فقط یک خط هزینه دارد و جلوی باگ‌های گیج‌کننده را در آینده می‌گیرد.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&#34;یک-دکوریتور-کاربردی-زمانسنجی&#34;&gt;یک دکوریتور کاربردی: زمان‌سنجی&lt;/h2&gt;
&lt;p&gt;بیایید چیزی مفید بسازیم: دکوریتوری که گزارش می‌دهد یک تابع چقدر طول می‌کشد.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;functools&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wraps&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;timed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;nd&#34;&gt;@wraps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;start&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;perf_counter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;finally&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;elapsed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;perf_counter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;start&lt;/span&gt;
            &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; took &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;elapsed&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.3f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;s&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wrapper&lt;/span&gt;

&lt;span class=&#34;nd&#34;&gt;@timed&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;build_report&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;build_report&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5_000_000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;# build_report took 0.312s&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;try&lt;/code&gt;/&lt;code&gt;finally&lt;/code&gt; مطمئن می‌شود که زمان حتی اگر تابع خطا بدهد چاپ شود.&lt;/p&gt;
&lt;h2 id=&#34;دکوریتورهایی-که-آرگومان-میگیرند&#34;&gt;دکوریتورهایی که آرگومان می‌گیرند&lt;/h2&gt;
&lt;p&gt;اگر بخواهید &lt;code&gt;@retry(times=3)&lt;/code&gt; بنویسید چه؟ آن‌وقت به &lt;strong&gt;یک لایهٔ دیگر&lt;/strong&gt; نیاز دارید: تابعی که آرگومان‌ها را می‌گیرد و &lt;em&gt;یک دکوریتور برمی‌گرداند&lt;/em&gt;.&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;functools&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wraps&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;retry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;delay&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exceptions&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;Exception&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,)):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;decorator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;nd&#34;&gt;@wraps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;attempt&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;times&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
                    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exceptions&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
                    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;attempt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
                        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt;
                    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Attempt &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;attempt&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; failed: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;. Retrying in &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;delay&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;s…&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
                    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;delay&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wrapper&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;decorator&lt;/span&gt;

&lt;span class=&#34;nd&#34;&gt;@retry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;delay&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exceptions&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;ConnectionError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,))&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fetch_prices&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;@retry(times=5)&lt;/code&gt; اول &lt;code&gt;retry(...)&lt;/code&gt; را &lt;em&gt;صدا می‌زند&lt;/em&gt; که &lt;code&gt;decorator&lt;/code&gt; را برمی‌گرداند و بعد آن روی &lt;code&gt;fetch_prices&lt;/code&gt; اعمال می‌شود. سه لایه پیچیده به نظر می‌رسد، اما هر کدام فقط یک وظیفه دارد:&lt;/p&gt;
&lt;div class=&#34;table-wrap&#34;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;لایه&lt;/th&gt;
&lt;th&gt;دریافت می‌کند&lt;/th&gt;
&lt;th&gt;برمی‌گرداند&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;retry&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;تنظیمات (&lt;code&gt;times&lt;/code&gt;، &lt;code&gt;delay&lt;/code&gt;…)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;decorator&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;decorator&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;تابعی که باید پوشانده شود&lt;/td&gt;
&lt;td&gt;&lt;code&gt;wrapper&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wrapper&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;آرگومان‌های هر فراخوانی&lt;/td&gt;
&lt;td&gt;نتیجهٔ تابع&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&#34;دکوریتورهای-داخلی-که-باید-بشناسید&#34;&gt;دکوریتورهای داخلی که باید بشناسید&lt;/h2&gt;
&lt;p&gt;پایتون چند دکوریتور عالیِ آماده دارد. مثلاً لازم نیست کش را خودتان بنویسید، چون &lt;code&gt;functools.cache&lt;/code&gt; (پایتون ۳.۹ به بعد) این کار را برایتان انجام می‌دهد:&lt;/p&gt;
&lt;figure class=&#34;code-block&#34;&gt;&lt;pre class=&#34;highlight&#34;&gt;&lt;code&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;functools&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cache&lt;/span&gt;

&lt;span class=&#34;nd&#34;&gt;@cache&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fibonacci&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fibonacci&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fibonacci&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fibonacci&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# 354224848179261915075, instantly&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;بدون &lt;code&gt;@cache&lt;/code&gt;، این بازگشتِ ساده بیش از ۱۰ به توان ۲۰ فراخوانی تابع انجام می‌داد. با آن، هر مقدار دقیقاً یک بار محاسبه می‌شود. اگر لازم است مصرف حافظه را محدود کنید، از &lt;code&gt;functools.lru_cache(maxsize=…)&lt;/code&gt; استفاده کنید.&lt;/p&gt;
&lt;p&gt;دکوریتورهای داخلیِ دیگری که ارزش شناختن دارند:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@property&lt;/code&gt; یک متد را به شکل یک ویژگیِ فقط‌خواندنی در اختیار می‌گذارد.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@staticmethod&lt;/code&gt; و &lt;code&gt;@classmethod&lt;/code&gt; متدهایی تعریف می‌کنند که به نمونه (instance) نیاز ندارند.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@dataclass&lt;/code&gt; متدهای &lt;code&gt;__init__&lt;/code&gt;، &lt;code&gt;__repr__&lt;/code&gt; و &lt;code&gt;__eq__&lt;/code&gt; را برایتان می‌سازد.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@contextlib.contextmanager&lt;/code&gt; یک generator را به context manager برای دستور &lt;code&gt;with&lt;/code&gt; تبدیل می‌کند.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;جمعبندی&#34;&gt;جمع‌بندی&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;توابع شیء هستند: می‌توان آن‌ها را جابه‌جا کرد، برگرداند و داخل توابع دیگر تعریف کرد.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;دکوریتور&lt;/strong&gt; یک تابع می‌گیرد و نسخهٔ پوشانده‌شدهٔ آن را برمی‌گرداند؛ &lt;code&gt;@deco&lt;/code&gt; خلاصهٔ &lt;code&gt;func = deco(func)&lt;/code&gt; است.&lt;/li&gt;
&lt;li&gt;برای پشتیبانی از هر امضایی از &lt;code&gt;*args, **kwargs&lt;/code&gt; استفاده کنید و &lt;strong&gt;همیشه&lt;/strong&gt; &lt;code&gt;@functools.wraps&lt;/code&gt; را به کار ببرید.&lt;/li&gt;
&lt;li&gt;دکوریتورهایی که آرگومان می‌گیرند یک لایهٔ اضافه لازم دارند: تابعی که دکوریتور را برمی‌گرداند.&lt;/li&gt;
&lt;li&gt;پیش از نوشتن دکوریتور خودتان، سراغ نمونه‌های داخلی مثل &lt;code&gt;@cache&lt;/code&gt;، &lt;code&gt;@property&lt;/code&gt; و &lt;code&gt;@dataclass&lt;/code&gt; بروید.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;چالش:&lt;/strong&gt; یک دکوریتور &lt;code&gt;@log_calls&lt;/code&gt; بنویسید که هر بار تابع صدا زده می‌شود، نام و آرگومان‌هایش را چاپ کند. بعد آن را همراه با &lt;code&gt;@timed&lt;/code&gt; روی هم بگذارید و ببینید به چه ترتیبی اجرا می‌شوند.&lt;/p&gt;</content:encoded>
    </item>
  </channel>
</rss>