عمومیکسب و کار ایرانیان

آموزش کامل کار با دیکشنری در پایتون به همراه ترفند

دیکشنری در پایتون و متدهای مورد استفاده

یکی از محبوب‌ترین زبان‌های برنامه‌نویسی است. پایتون یک زبان برنامه نویسی همه منظوره است و بسیاری از وبسایت‌ها و نرم‌افزارهای شناخته شده با این زبان نوشته شده‌اند. پایتون زبان قدرتمندی است که توانایی‌ها و ویژگی‌های بسیاری دارد؛ یکی از این ویژگی‌ها دیکشنری می باشد؛ حتما تا به حال از دیکشنری استفاده کرده‌اید و با روش کار با آن‌ها آشنا هستید.

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

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

مفهوم دیکشنری در پایتون

در رابطه با دسترسی و مدیریت دیکشنری ها یاد می‏گیریم. در این آموزش  تلاش شده است که بر تمام مفاهیم دیکشنری‌ها مروری داشته باشیم. دیکشنری در پایتون Python Dictionaries نوع دیگری از داده‏‌های مرکب است که بسیار شبیه به لیست‌‏ها است. دیکشنری‌ها (Dictionary) مشابه آرایه‌ها (Associative Array) در زبان‌هایی مانند جاوا و php هستند.

در لیست‌ها ترتیب اهمیت دارد و عناصر با ترتیب خاصی ذخیره شده‌اند، اندیس‌های عناصر، عددی هستند و اولین عنصر درون لیست و تاپل عدد صفر و دومین عنصر اندیس ۱ و الی آخر؛ در دیکشنری پایتون نوع دسترسی به مقادیر دیکشنری با لیست‌ها و تاپل‌ها متفاوت است؛ گرچه لیست‌ها و دیکشنری‌ها در پایتون بی شباهت به یکدیگر هم نیستند.

دیکشنری‏‌ها در پایتون و لیست‌‏ها شباهت‌های بسیاری دارند:

  • هردو تغییرپذیر هستند.
  • هردو پویا هستند و در صورت نیاز می‏توان آن ها را گسترش داد یا کوتاه کرد.
  • هردو می‏‌توانند تودرتو باشند. یک لیست می‏‌تواند شامل یک لیست دیگر باشد و یک دیکشنری در پایتون هم می‏‌تواند شامل دیکشنری دیگری باشد. همچنین یک دیکشنری در پایتون می‏‌تواند شامل یک لیست باشد و بالعکس.

دیکشنری ها پایتون

دیکشنری‌ها می‌توانند هر نوعی از داده باشند، اما غالبا از نوع داده‌ی عددی یا رشته‌ای هستند، در دیکشنری در پایتون بیشتر از داده‌های عددی و رشته‌ای استفاده کرده ایم. دیکشنری‌ها با کروشه یا {} تعریف می‌شوند و جهت دسترسی به مقادیر آن بایستی از آکولاد یا عملگر [] کمک گرفت. در واقع دیکشنری مجموعه‌ای از جفت داده‌های به هم مرتبط می‌باشد. اطلاعاتی که در داخل دیکشنری‌ها قرار می گیرند معمولا به یکدیگر مرتبط هستند.

اما دیکشنری‏‌ها در مورد نوع دسترسی به المنت‏‌ها با لیست‏‌ها تفاوت دارند. در لیست‏ها المنت‏ها به صورت مرتب قرار گرفته‌اند و دسترسی به آن‌ها نیز با توجه به محل قرارگیری آن‌ها در لیست امکان پذیر است. در این آموزش دیکشنری در پایتون تعریف و دسترسی به مقادیر دیکشنری‌ها به طور کامل به شما آموزش داده می‌شود.

تعریف دیکشنری در پایتون

پیاده سازی دیکشنری در پایتون مشابه تعریف آرایه است. به طور کلی دیکشنری ها مجموعه ای از جفت کلید-مقدار هستند. همچنین باید در نظر داشته باشید که یک کلید می‌تواند تعداد بیشتری مقدار داشته باشد، یعنی می‌توانیم توضیحات بیشتری را به یک کلید نسبت دهیم.

  1. شما می‌توانید یک دیکشنری را داخل یک جفت نماد حایل ({}) تعریف کنید. هر عنصر درون دیکشنری با ویرگول از عنصر بعدی جدا می‌شود و هر عنصر به صورت یک زوج key : value است که key نقش اندیس و value مقدار انتساب داده شده به اندیس را دارند، یک دو نقطه هر کلید را از مقدارش مجزا می‌کند:
  2. شما همچنین می‌توانید برای تعریف دیکشنری از تابع از پیش تعریف شده پایتون “(dict)” استفاده کنید، در این آموزش دیکشنری در پایتون بیشتر از روش اول استفاده شده است.

آرگومان داخل این تابع باید به صورت جفت کلید-مقدار باشد:یکبار که یک دیکشنری را تعریف کردید، می‌توانید هر زمان که بخواهید محتوای آن را نمایش دهید.

نمایش محتوای دیکشنری در پایتون

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

دسترسی به محتوای دیکشنری

شما می‌توانید تمام محتوای یک دیکشنری را یکجا مشاهده کنید و یا هر مقدار را به صورت مجزا مشاهده کنید. همچنین می‌توانید روی محتوای دیکشنری یک چرخه ایجاد کنید. دسترسی به محتوای دیکشنری توسط کلیدها صورت می‌گیرد. یکی از ساده‌ترین راه‌ها برای دسترسی به محتوای دیکشنری این است که می‌توان با قرار دادن کلید مورد نظر داخل نماد ([]) به المنت مورد نظر دسترسی پیدا کرد:

مطمئنا با تابع (print) در پایتون آشنا هستید، شما به سادگی می‌توانید با قرار دادن کلید داخل تابع به صورت مقابل (print(team[‘perspolis’])، مقدار آن را مشاهده کنید. شما همچنین می‌توانید با قرار دادن نام دیکشنری در تابع پرینت تمام محتوای دیکشنری را نمایش دهید. اما با این کار تنها می‌توانید از محتوای داخل دیکشنری مطلع شوید؛ در ادامه با اینکه چگونه می‌توانید این محتوا را تغییر دهید و یا چه نوع تغییراتی می‌توانید در این محتوا اعمال کنید، آشنا خواهید شد.

همانطور که در این آموزش دیکشنری در پایتون گفته شد، دیکشنری ها پویا هستند، به این معنی که هر زمان که بخواهید می‌توانید آن ها را به‌روز رسانی کنید ( کلید-مقدار جدیدی اضافه کنید، کلید-مقداری را حذف کنید، مقداری را بازنویسی کنید). برای حذف یکی از مقادیر از عبارت “del dictionary name” استفاده می‌کنیم.

نحوه اضافه و حذف کردن کلید-مقدار از دیکشنری

*هر چند که دسترسی به مقادیر دیکشنری به ترتیب آن ها ارتباطی ندارد، اما پایتون ترتیب‌ها را به همان صورت که کلید-مقدارها تعریف شده‌اند، حفظ می‌کند و در زمان نمایش آن‌ها را به همان صورت نمایش می‌دهد. همچنین زمانی که یک کلید-مقدار جدید تعریف می‌کنید، محتوای جدید در انتهای دیکشنری قرار می‌گیرد و زمانی که یک کلید-مقدار را از دیکشنری حذف می‌کنید نیز ترتیب مقادیر باقی مانده به همان صورت حفظ می‌شود.

در تعریف دیکشنری می‌توانید داخل یک دیکشنری انواع محتوا را مانند: اعداد، لیست، رشته و یا دیکشنری دیگر داشته باشید. همچنین همان‌گونه که در تعریف مقادیر محدودیت به خصوصی وجود ندارد در تعریف کلیدها نیز به همین صورت است.

در صورتی که بخواهید می توانید یک دیکشنری خالی تعریف کنید و هر زمان که بخواهید در آن محتوا قرار دهید:

انواع محتوا در دیکشنری

برای دسترسی به لیستی که در داخل یک دیکشنری تعریف شده است، به ایندکس آن لیست نیاز داریم؛ همچنین برای دسترس به مقادیر دیکشنری که در داخل یک دیکشنری دیگر تعریف شده است، به کلید دیکشنری ذکر شده نیاز داریم:

دسترسی به محتوای لیست ها و دیکشنری در داخل یک دیکشنری همانطور که گفته شد در انتخاب کلید در دیکشنری نیازی نیست همه کلیدها نوع یکسانی داشته باشند:

انواع کلید در دیکشنری

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

محدودیت های کلیدهای دیکشنری

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

اما محدودیت هایی که در انتخاب کلیدها وجود دارد:

  1. هر کلید تنها یکبار می‌تواند تعریف شود. پایتون کلیدهای تکراری را نمی‌پذیرد. دیکشنری هر کلید را به مقدار مشخصی نسبت می‌دهد، در نتیجه استفاده از یک برای مقادیر متفاوت اشتباه است. در صورتی که پس از تعریف یک کلید مجددا برای کلید مورد نظر مقدار دیگری تعریف کنید، محتوای کلید بازنویسی می‌شود و مقدار اولیه از بین می‌رود.
  2. کلیدهای انتخابی باید تغییر ناپذیر باشند مانند: int, string, Boolean. زوج مرتب هم می‌تواند به عنوان کلید به‌کار رود. اما لیست و دیکشنری نمی‌توانند به عنوان کلید در نظر گرفته شوند زیرا هردو تغییرپذیر هستند.
  3. دیکشنری در پایتون به بزرگ و کوچک بودن حروف حساس است؛ به این معنی که یک کلید را می‌توان یکبار با حروف کوچک و بار دیگر با حروف بزرگ نوشت و دیکشنری پایتون هر یک را به عنوان کلید مجزا در نظر می‌گیرد.
  4. همانطور که  مشاهده کردید هیچ محدودیتی در رابطه با محتوای دیکشنری وجود ندارد و تمام انواع داده، حتی لیست ها و دیکشنری ها نیز می توانند به عنوان محتوای یک دیکشنری تعریف شوند.

متدهای از پیش ساخته شده پایتون

مشابه لیست ها چندین متد از پیش ساخته شده در پایتون وجود دارد که برای دیکشنری‌ها نیز قابل پیاده‌سازی است که در ادامه به آن ها می‌پردازیم:

  •  (Dictionaryname.clear)
  • تمام محتوای دیکشنری یعنی تمام کلید-مقدارها را پاک می‌کند و دیکشنری را خالی می‌کند.
  • (‘Dictionaryname.get key’)
  • متد .(get) پایتون راه ساده‌‎ای برای دسترسی به محتوای مدنظرمان است. در واقع این متد کلید نام برده ما را صرف نظر از اینکه وجود دارد یا خیر جستجو کرده و نتیجه را بر می گرداند:
  • مثالی از کاربرد .clear) , .get)

آموزش دیکشنری در پایتون Dictionaryname.items

این متد لیستی از زوج کلید-مقدار را به عنوان نتیجه بر می گرداند. اولین آیتم در هر زوج مرتب کلید و دومین آیتم مقدار کلید است.

 Dictionaryname.keys

این متد لیستی از تمام کلیدهای موجود در دیکشنری را نمایش می‌دهد مثالی از متدهای .items) , .keys)

Dictionaryname.values

این متد مشابه متد .(items) است با این تفاوت که (values) لیستی از مقادیر موجود در دیکشنری را برمی‌گرداند و کاری به کلیدهای آن‌ها ندارد. هر عنصر به هر تعداد که در دیکشنری تکرار شده باشد به همان تعداد در نتیجه نمایش داده می شود.

کلید مورد نظرمان را از دیکشنری پاک کرده و مقدار آن را نمایش می دهد.

مشاهده می کنید که زمانی که این متد را اجرا می‌کنیم کلید نام برده ما یعنی ” c ” در دیکشنری موجود است، در نتیجه این کلید حذف و مقدار آن نمایش داده می‌شود. اما هنگامی که کلید” z ” را به متد می دهیم، به خاطر اینکه این کلید در دیکشنری موجود نیست با پیغام خطا مواجه می‌شویم.

 Dictionaryname.popitem

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

 Dictionaryname.update

یک دیکشنری را با یک دیکشنری دیگر و یا زوج کلید-مقدار ادغام می کند.
در حالتی که obj یک دیکشنری باشد:

  • اگر کلید در دیکشنری ما وجود نداشته باشد، کلید از داخلobj به دیکشنری ما اضافه می‌شود.
  • اگر کلید در دیکشنری ما موجود باشد، مقدار آن به مقدار کلید مشابه از obj تغییر پیدا می‌کند.

همانطور که در مثال بالا مشاهده می‌کنید، در ادغام دو دیکشنری f,g دو کلید”q” و “o” به دیکشنری f اضافه شده‌اند و دو کلید “a” و “m” که در دیکشنری f وجود دارند، بازنویسی شده‌اند. برای ادغام یک یا چند کلید با یک دیکشنری به دو صورت می‌توان عمل کرد:

  1. وارد کردن کلید-مقدار به صورت زوج مرتب
  2.  وارد کردن آنها به صورت لیستی از کلیدها همراه با مقادیرشان

Dictionaryname.setdefault

این متد یک کلید و مقدار را به عنوان ورودی می گیرد و در دیکشنری مورد نظرمان به دنبال کلید ذکر شده می گردد، در صورتی که کلید مورد نظر دارای مقدار بود، آن مقدار را بر می گرداند، در غیر این صورت مقداری که به متد داده شده بود به عنوان محتوای آن کلید در نظر گرفته می شود.

این متد راه دیگری برای دسترسی به محتوای دیکشنری می باشد. در زمان استفاده از این متد ذکر نام کلید اجباری است اما قرار دادن مقدار اجباری نیست.

 Dictionaryname.copy

یک کپی از دیکشنری موجود ایجاد می کند. هیچ المنت ورودی ندارد. (Len) درصورتی که بخواهید می توانید با استفاده ای این متد اندازه دیکشنری را به دست آورید.مثالی از متد (len)

 مرور و نمایش محتوای دیکشنری(ایجاد چرخه روی دیکشنری)

اگر با نوشتن for در پایتون آشنا باشید، این کار بسیار ساده است. تنها لازم است چرخه loop و یکی از متدهایی را که بالاتر گفته شد، ادغام کنید؛ در واقع باید با استفاده از یک چرخه برای هر یک از کلید-مقدار ها یکبار متد موردنظرتان را اجرا کنید.

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

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

  •  اطلاعات در دیکشنری‌ها بدون ترتیب و مانند نقشه ذخیره می‌شود.
  • دیکشنری در پایتون مشابه دیکشنری در دنیای واقعی است و کار کردن با آن هم ملزم دانستن کلمه کلیدی بوده و بسیار ساده است

معمولاً از دیکشنری پایتون در جاهایی استفاده می‌کنیم که نیاز داریم مقادیری را با استفاده از یک کلید مرتبط با هر کدام از آن‌ها شناسایی کنیم. این مقادیر هر چیزی می‌توانند باشند؛ برای مثال، رشته متنی، عدد، شئ و … .

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

دیکشنری (Dictionary) در زبان فارسی معادل فرهنگ لغت یا واژه‌نامه است. در یک کتاب فرهنگ لغت، یک کلمه با معادلش مرتبط می‌شود. این معادل می‌تواند یکی بوده یا چندین مورد باشد، اما کلمه اصلی یکی است! در اصل یک یا چند معنی معادل را به یک کلمه مرتبط کرده‌ایم.

در دیکشنری پایتون هم دقیقاً مشابه چنین کاری را انجام می‌دهیم؛ یک کلمه (که آن را به عنوان کلید می‌شناسیم) با یک مقدار (string، عدد، رفرنس شئ و …) مرتبط خواهد شد.

معمولاً اعضای یک دیکشنری مواردی مرتبط با هم هستند و هر یک از اعضا یک خصیصه یا ویژگی از مورد اصلی را بیان می‌کنند. اما این مسئله تماماً وابسته به تعاریف و نوع برنامه‌نویسی شما به عنوان برنامه‌نویس خواهد بود و هیچ قاعده و قانون خاصی در مورد مرتبط بودن اعضای یک دیکشنری نداریم!

ساخت دیکشنری در پایتون

یک دیکشنری با علامت { شروع شده و با } خاتمه می‌یابد. اعضای کی دیکشنری به صورت کلید و مقدار (key value) در درون آن تعریف شده و مشابه سایر ساختارهای رایج ذخیره‌سازی در پایتون، با استفاده از کاما (,) از یکدیگر جدا می‌شوند.

برای مثال فرض کنید می‌خواهیم مشخصات فردی را درون یک دیکشنری داشته باشیم؛ دیکشنری را به صورت زیر تعریف می‌کنیم.

person  = {    “name”: “hesam”,    “job”: “graphist”,    “car”: “BMW x6”,    “age”: 24,    “code”: 134}

به همین سادگی توانستیم یک دیکشنری حاوی اطلاعات فردی به نام hesam را ایجاد کنیم!

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

ساخت دیکشنری با سازنده dict

برای ایجاد دیکشنری می‌توان از سازنده (Constructor) آن نیز استفاده کرد. به این منظور تابع dict() را صدا زده و تمام کلیدها و مقادیر آن‌ها را به صورت پارامترهای جداگانه به عنوان ورودی به تابع می‌دهیم.

person = dict( name=”hesam”, job=”graphist”, car=”BMW x6″, age=24, code=134 )

نتیجه ذخیره شده در متغیر person نیز مشابه حالت قبل است. در حقیقت تفاوت خاصی در دیکشنری ایجاد شده در این دو حالت وجود ندارد. شما می‌توانید با هر روشی که راحت‌تر هستید از آن‌ها استفاده کنید.

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

کار با دیکشنری در پایتون

تا به این جای کار توانستیم یک دیکشنری در پایتون بسازیم. قطعاً لازم است بتوانیم با عناصر موجود در آن عملیات‌هایی انجام داده تا برنامه خود را پیش ببریم. در ادامه روش‌های کار با عناصر دیکشنری را می‌خوانیم.

دسترسی به مقادیر دیکشنری

برای دسترسی به مقادیر (عناصر) ذخیره‌شده در دیکشنری، دو راه وجود دارد.

راه اول و ساده‌ترین راه‌حل مشابه دسترسی به خانه‌های یک است. به این صورت که با استفاده از علامت [] می‌توان به تک تک عناصر دسترسی داشت؛ با این تفاوت که به جای مقدار عددی برای اَندیس، از مقدار کلید‌ها به عنوان ایندکس استفاده خواهیم کرد.

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

print( “Name: ” + person[“name”] )

خروجی قطعه کد بالا چیزی شبیه زیر خواهد شد:

Name: hesam

راهکار دوم برای دسترسی به مقدار یک کلید در دیکشنری پایتون، استفاده از تابع get() روی دیکشنری است. این تابع یک ورودی می‌گیرد که همان کلید مورد نظر ماست و سپس مقدار مرتبط با کلید را بازمی‌گرداند.

print( “Name: ” + person.get(“name”) ) # output: Name: hesam

خطای KeyError در دیکشنری پایتون

اگر در هنگام فراخوانی یک مقدار از دیکشنری، کلیدی را صدا بزنیم که وجود نداشته باشد، با خطایی از نوع KeyError مواجه خواهیم شد. (یادگیری بیشتر: )

info = {‘name’: ‘omid’, ‘job’: ‘programmer’, ‘code’: 177}print( info[‘name’] )print( info[‘family’] ) # omid# KeyError: ‘family’

تغییر مقادیر دیکشنری در پایتون

برای به‌روز‌رسانی مقدار هر یک از کلیدها مشابه تخصیص مقدار به ایندکس‌های مختلف یک لیست عمل می‌کنیم.

در قطعه کد زیر، مقدار 23 را در کلید age از دیکشنری person قرار داده‌ایم.

person[“age”] = 23

همان‌طور که احتمالاً درست حدس زده‌اید، می‌توان برای به‌روز‌رسانی مقدار یک کلید در دیکشنری از همان مقدار یا مقدارهای دیگر درون آن دیکشنری نیز استفاده کرد.

مثلاً در مثال زیر، سن فعلی کاربر را به اندازه یک واحد افزایش می‌دهیم.

person[“age”] = person[“age”] + 1

ترفندهای کار با دیکشنری پایتون

افزودن عنصر جدید به دیکشنری پایتون

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

person[“mobile”] = “Samsung Galaxy Note 7”

حذف عناصر از دیکشنری

برای حذف یک کلید و مقدار مرتبط با آن، دو روش خواهیم داشت.

print( person )del person[“mobile”]   # delete ‘mobile’ key in dictionaryprint( person )

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

{‘name’: ‘hesam’, ‘job’: ‘graphist’, ‘car’: ‘BMW x6’, ‘age’: 24, ‘code’: 134, ‘mobile’: ‘Samsung Galaxy Note 7’}{‘name’: ‘hesam’, ‘job’: ‘graphist’, ‘car’: ‘BMW x6’, ‘age’: 24, ‘code’: 134}

برای حذف یک المان از دیکشنری استفاده از متد pop() در دیکشنری پایتون است. این تابع به صورت متد روی دیکشنری مورد نظر صدا زده شده و یک ورودی می‌گیرد.

ورودی آن همان مقدار کلید مورد نظر ماست که می‌خواهیم از دیکشنری حذف کنیم.

person.pop(“car”)

حذف کل دیکشنری در پایتون

گاهی لازم است تا کل دیکشنری را حذف کنیم. منظور از کل دیکشنری، حذف تمام کلید‌ها و مقدار‌ها و پس از آن حذف متغیر دیکشنری است.

برای این کار کافی است تا نام دیکشنری را در مقابل دستور del بنویسیم. با این کار کل دیکشنری حذف خواهد شد.

del person   # delete person dictionary object

حذف تمام عناصر دیکشنری

اما گاهی نیاز است که صرفاً دیکشنری را خالی کنیم؛ یعنی بدون حذف خود دیکشنری، فقط کلید‌ها و مقدار‌ها را حذف کنیم. برای این کار متد clear() را روی شیء دیکشنری صدا می‌زنیم.

با صدا زدن این تابع، تمام کلیدهای موجود در دیکشنری حذف شده و در نهایت یک دیکشنری خالی خواهیم داشت.

person.clear() # delete all keys in Dictionaryprint( person ) # output: {}

قوانین تعریف کلید و مقدار در دیکشنری پایتون

کلیدهای دیکشنری در پایتون باید دو ویژگی اصلی داشته باشند.

  1. یکتا باشند (تکراری نباشند)
  2. تغییرناپذیر باشند.

مورد اول که تقریباً واضح است. در حقیقت به ازای هر کلید در دیکشنری نمی‌توان بیشتر از یک مقدار داشت. در صورتی که یک کلید دو بار در دیکشنری تعریف شود، مقدار دوم آن جایگزین اولی شده و همواره مقدار دوم را خواهیم داشت. (به نوعی تغییر مقدار صورت می‌گیرد)

در مورد دومین قانون، کلید را به عبارتی هویت مقدار (value) مرتبط با آن می‌دانند. می‌دانیم که هویت را نمی‌توان تغییر داد. بنابراین کلید‌ها در دیکشنری پایتون می‌بایست یک مقدار تغییرناپذیر باشند. در نتیجه نمی‌توان از یک متغیر به عنوان کلید استفاده کرد.

برای مقادیر متناظر با کلید‌ها در دیکشنری هیچ گونه محدودیتی نداریم. این مقادیر می‌توانند تکراری بوده یا از هر نوع داده‌ای مختلفی (نظیر ، عدد، شیء پایتون، شئ تعریف شده توسط کاربر و …) باشند؛ در نتیجه می‌توانند تغییرپذیر نیز باشند.

کپی کردن دیکشنری در پایتون

همان‌طور که می‌دانید، متغیرهایی که به اشیاء اشاره می‌کنند حاوی رفرنسی به آن شئ هستند. پس اگر یک دیکشنری را با استفاده از علامت تخصیص (=) به متغیر دیگری بدهیم، دیکشنری کپی نمی‌شود؛ بلکه فقط رفرنس آن، درون متغیر دوم ریخته خواهد شد. در نتیجه با تغییر دیکشنری اول، دیکشنری دوم ما نیز تغییر می‌کند.

person_backup = person   # not a true way to copy dictionary

برای کپی کردن دیکشنری در پایتون می‌توان از متد copy() روی شیء دیکشنری استفاده کرد. (یادگیری بیشتر: )

person_backup = person.copy()

حالا اگر دیکشنری person یا person_backup را تغییر دهیم، محتوای دیکشنری دیگر هیچ تغییری نخواهد کرد.

برای دیدن تمام متدهای دیکشنری پایتون می‌توانید به جدول انتهای  مراجعه کنید.

جمع‌بندی: دیکشنری در پایتون چیست ؟

دیکشنری در پایتون نوعی لیست انجمنی یا کلید-مقدار است. اگر با لیست‌ها در پایتون آشنایی داشته باشید، می‌دانید که در لیست برای دسترسی به هر عنصر از اندیس استفاده می‌کنیم. در دیکشنری اندیس (یا همان کلید) هر مقدار (value) را خودمان تعریف خواهیم کرد.

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

به نظر شما چه ترفندهایی در کار با دیکشنری پایتون کاربردی است که به آن اشاره‌ای نشده؟ این ترفند را از بخش دیدگاه‌ها با دوستانتان به اشتراک بگذارید. اگر سؤالی دارید، باز هم بخش دیدگاه‌ها برای شماست!

این آموزش برای همیشه رایگانه! می‌تونید با اشتراک‌گذاری لینک این صفحه از ما حمایت کنید یا با خرید یه فنجون نوشیدنی بهمون انرژی بدید

پرینت همه جفت‌های کلید: مقدار در دیکشنری‌های تودرتو

این یک راه‌حل بازگشتی برای پرینت کردن همه جفت‌های کلید: مقدار در یک دیکشنری است که وجود لیست‌ها، مجموعه‌ها و چندتایی‌ها را در یک مقدار نیز مدیریت می‌کند:

import requestsimport json def recursive_key_values(dictionary):    “””recursive_key_values.        Print all keys and values anywhere in a dictionary    Args:        dictionary: any dictionary    Returns:        tuple:    “””    for key, value in dictionary.items():        i = 0        if type(value) is str:            yield (key, value)        elif type(value) is dict:            yield from recursive_key_values(value)        elif type(value) in (list, tuple, set):            for seq_item in value:                yield from recursive_key_values({f”{key}_{str(i)}”: seq_item})                i = i + 1        else:            yield (key, str(value)) mydata: dict = {    “key2”: {        “key2.0”: “value1”,        “key2.1”:…,        “key2.2”: {            “key2.2.0”: “value2”        }    },    “key1”: {        “key1.0”: “value3”    },}mydata[“key3”] = {1, 2, 3} # setmydata[“key4”] = [4, 5, 6] # listmydata[“key5”] = (7, 8, 9) # tuple if __name__ == “__main__”:    for key, value in recursive_key_values(mydata):        print(f”{key}: {value}”)

خروجی کد فوق چنین است:

مرتب‌سازی یک دیکشنری

از پایتون نسخه 3.6 به بعد، دیکشنری‌ها به صورت پیش‌فرض ترتیب درج را حفظ می‌کنند. با این حال هنوز از امکان مرتب‌سازی پشتیبانی نمی‌کنند.

امکان دریافت یک دنباله تکرارپذیر از جفت‌های کلید: مقدار دیکشنری به صورت دنباله‌ای از چندتایی‌ها وجود دارد. سپس می‌توانیم این لیست از چندتایی‌ها را مجدداً به یک دیکشنری تبدیل کنیم تا ترتیب درج حفظ شود.

“””Sorting a dictionary to an Iterable of tuples.https://en.wikipedia.org/wiki/List_of_countries_and_dependencies_by_area””” countries: dict = {    “Taiwan”: 36193,    “Canada”: 9984670,    “United States”: 9525067,    “Russia”: 17098246,    “Argentina”: 2780400,    “Zambia”: 752612,    “China”: 9596961,} assert dict(sorted(countries.items(), key=lambda kv: kv[1], reverse=False)) == {    “Taiwan”: 36193,    “Zambia”: 752612,    “Argentina”: 2780400,    “United States”: 9525067,    “China”: 9596961,    “Canada”: 9984670,    “Russia”: 17098246,} assert dict(sorted(countries.items(), key=lambda kv: kv[1], reverse=True)) == {    “Russia”: 17098246,    “Canada”: 9984670,    “China”: 9596961,    “United States”: 9525067,    “Argentina”: 2780400,    “Zambia”: 752612,    “Taiwan”: 36193,} assert dict(sorted(countries.items(), key=lambda kv: kv[0], reverse=False)) == {   “Argentina”: 2780400,   “Canada”: 9984670,   “China”: 9596961,   “Russia”: 17098246,   “Taiwan”: 36193,   “United States”: 9525067,   “Zambia”: 752612,} assert dict(sorted(countries.items(), key=lambda kv: kv[0], reverse=True)) == {    “Zambia”: 752612,    “United States”: 9525067,    “Taiwan”: 36193,    “Russia”: 17098246,    “China”: 9596961,    “Canada”: 9984670,    “Argentina”: 2780400,}

ادغام دو دیکشنری

از پایتون نسخه 3.9 به بعد، عملگر ادغام | برای دیکشنری‌ها ارائه شده است. تا این زمان می‌توانستید از روش ادغام کپی سطحی استفاده کنید.

def merge_dictionaries(left: dict, right: dict) -> dict:    “””Merge two dictionaries using a shallow copy.”””    temp: dict = left.copy()    temp.update(right)    return temp countries: dict = {    “Taiwan”: 36193,    “Canada”: 9984670,    “United States”: 9525067,    “Russia”: 17098246,    “Argentina”: 2780400,    “Zambia”: 752612,    “China”: 9596961,} cities: dict = {    “Toronto”: [“Canada”, 6082000],    “New York City”: [“United States”, 18819000],    “Moscow”: [“Russia”, 12410000],    “Buenos Aires”: [“Argentina”, 14967000],    “Shanghai”: [“China”, 25582000],    “Lusaka”: [“Zambia”, 1747152],    “Taipei”: [“Taiwan”, 2646204],} assert merge_dictionaries(countries, cities) == {    “Taiwan”: 36193,    “Canada”: 9984670,    “United States”: 9525067,    “Russia”: 17098246,    “Argentina”: 2780400,    “Zambia”: 752612,    “China”: 9596961,    “Toronto”: [“Canada”, 6082000],    “New York City”: [“United States”, 18819000],    “Moscow”: [“Russia”, 12410000],    “Buenos Aires”: [“Argentina”, 14967000],    “Shanghai”: [“China”, 25582000],    “Lusaka”: [“Zambia”, 1747152],    “Taipei”: [“Taiwan”, 2646204],}

ساخت دیکشنری از دو لیست

ما می‌توانیم دو لیست را از یک دنباله از چندتایی‌ها zip کنیم و آن را به سازنده dict()‎ بفرستیم:

def dict_from_two_lists(keys: list, values: list) -> dict:    “””    Args:        keys: The list of keys for the dictionary        values: The list of values for the dictionary    Returns: A dictionary of key:value pairs    “””    if len(keys) != len(values):        raise ValueError(“Lists must be of same length”)     return dict(zip(keys, values)) assert dict_from_two_lists([“first”, “second”, “third”],                           [“primary”, “secondary”, “tertiary”]) == {                               “first”: “primary”,                               “second”: “secondary”,                               “third”: “tertiary”,                           }

دریافت همه آیتم‌ها بر اساس کلید در یک دیکشنری تودرتو

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

import jsonimport requests def get_values_by_key(dictionary: dict, key: str) -> dict:    “””get_values_by_key.    Args:        dictionary (dict): dictionary        key (str): key    Returns:        dict:    “””    if isinstance(dictionary, dict):        for k, v in dictionary.items():            if k == key:                yield v            elif isinstance(v, dict):                for result in get_values_by_key(v, key):                    yield result            elif type(v) in (list, tuple):                for d in v:                    for seq in get_values_by_key(d, key):                        if type(seq) in (list, tuple):                            for inner_item in seq:                                yield inner_item                        else:                            yield seq dict1 = dict(    json.loads(        requests.get(“http://ergast.com/api/f1/2004/1/results.json”).text)) assert “http://en.wikipedia.org/wiki/McLaren” in list(    get_values_by_key(dict1, “url”))

دریافت همه آیتم‌ها بر اساس مقدار در دیکشنری تودرتو

طرز کار این مثال همانند ترفند قبلی است. توجه داشته باشید که ما از yield برای ساخت یک تکرارکننده استفاده کرده‌ایم. خط 32 همه اجراهای منفرد yield را به یک لیست کاهش می‌دهد:

import jsonimport requests def get_key_by_value(dictionary: dict, val: str) -> object:    “””get_values_by_key.    Args:        dictionary (dict): dictionary        val (str): value    Returns:        dict:    “””    if isinstance(dictionary, dict):        for k, v in dictionary.items():            if val == v:                yield k            elif isinstance(v, dict):                for result in get_key_by_value(v, val):                    yield result            elif isinstance(v, list):                for list_item in v:                    for result in get_key_by_value(list_item, val):                        yield result dict1 = dict(    json.loads(        requests.get(“http://ergast.com/api/f1/2004/1/results.json”).text)) assert “raceName” in list(get_key_by_value(dict1, “Australian Grand Prix”))

ایجاد دیکشنری با استفاده از خلاصه‌سازی دیکشنری

«خلاصه‌سازی دیکشنری» (Dictionary Comprehension) از سازنده {key: value} با یک حلقه for روی یک دنباله استفاده می‌کند:

asci_uppercase: dict = {i: chr(+i) for i in range(65, 91, 1)}digits: dict = {i: chr(+i) for i in range(48, 58, 1)}asci_lowercase: dict = {i: chr(+i) for i in range(97, 123, 1)}asci_punctuation: dict = {i: chr(+i) for i in range(32, 48, 1)}asci_punctuation.update({i: chr(+i) for i in range(123, 127, 1)})asci_punctuation.update({i: chr(+i) for i in range(91, 97, 1)})asci_punctuation.update({i: chr(+i) for i in range(58, 65, 1)})asci_extended: dict = {i: chr(+i) for i in range(128, 255, 1)}asci_system: dict = {i: hex(i) for i in range(0, 32, 1)} ascii_chars: dict = {}ascii_chars.update({“asci_punctuation”: asci_punctuation})ascii_chars.update({“asci_lowercase”: asci_lowercase})ascii_chars.update({“asci_uppercase”: asci_uppercase})ascii_chars.update({“digits”: digits})ascii_chars.update({“asci_extended”: asci_extended})ascii_chars.update({“asci_system”: asci_system}) print(ascii_chars)

استفاده از مقادیر پیش‌فرض برای آیتم‌های جدید

Defaultdict در مواردی که بخواهیم مقادیر را به یک کلید موجود الحاق کنیم به طوری که بازنویسی نشود، بسیار مفید خواهد بود. به طور معمول خط شماره 9 یک خطا ایجاد می‌کند، زیرا مقدار موجود در این کلید نمی‌تواند یک لیست باشد و باید None باشد. از این رو نمی‌توانستیم از append استفاده کنیم.

from collections import defaultdict as dd s = [(“John”, “Male”), (“John”, “48”), (“John”, “Married”), (“Jane”, “Female”),     (“Jane”, “25”)] dict1: dict = dd(list) for k, v in s:    dict1[k].append(v) assert dict1[“John”] == [“Male”, “48”, “Married”]assert dict1[“Jane”] == [“Female”, “25”]

تبدیل لیستی از چندتایی‌ها به دیکشنری

در این مورد نیز از یک defaultdict استفاده می‌کنیم، اما این بار مقدار پیش‌فرض یک دیکشنری است.

from collections import defaultdict as dd s = [(“John”, “Male”, 25), (“Fred”, “Female”, 48), (“Sam”, “Female”, 41),     (“Jane”, “Female”, 25)] dict1 = dd(dict) for name, gender, age in s:    dict1[name][“age”] = age    dict1[name][“gender”] = gender assert dict1[“John”] == {“age”: 25, “gender”: “Male”}assert dict1[“Fred”] == {“age”: 48, “gender”: “Female”}assert dict1[“Sam”] == {“age”: 41, “gender”: “Female”}assert dict1[“Jane”] == {“age”: 25, “gender”: “Female”

ایجاد یک دیکشنری از فایل CSV با عناوین ستون

به این منظور از اختراع مجدد چرخ خودداری کرده و از ماژول CSV کمک می‌گیریم.

from collections import defaultdict as ddimport csvimport requests url: str = “https://data.london.gov.uk/download/london-borough-profiles/c1693b82-68b1-44ee-beb2-3decf17dc1f8/london-borough-profiles.csv ” boroughs = (requests.get(url).text).split(“\n”)reader = csv.DictReader(boroughs, dialect=”excel”)dict1 = dd(dict) for row in reader:    dict1[row[“Code”]] = row assert dict1[“E09000001”][“Area_name”] == “City of London”assert dict1[“E09000032”][“Inner/_Outer_London”] == “Inner London”

حذف آیتم از دیکشنری

با استفاده از متد pop()‎ می‌توانید یک آیتم دیکشنری را حذف کرده و مقدار آن را بازیابی کنید.

digits: dict = {i: chr(+i) for i in range(48, 58, 1)}key = 50 try:    val = digits.pop(key)except KeyError:    print (f”The item with key {key} did not exist.”)else:    print(f”Deleted item with key {key} with value {val}.”)

ایجاد کپی عمیق از دیکشنری

با استفاده از تابع deepcopy در ماژول copy می‌توانید یک کپی واقعی از یک دیکشنری بسازید که شامل اشیای تغییرپذیر مانند یک لیست باشد.

import copy original = {}original[“object1”] = dict({“a”: {“b”: [1, 2, 3]}}) dict_shallow = original.copy()dict_deep = copy.deepcopy(original) # change the mutable object in original and dict_shalloworiginal[“object1”][“a”][“b”] = [3, 4, 5] assert id(original[“object1”]) == id(dict_shallow[“object1”])assert id(original[“object1”]) != id(dict_deep[“object1”])

معکوس ساختن کلیدها و مقادیر

این ترفند نیز ممکن است یک روز به کارتان بیاید. در این راه‌حل از یک خلاصه‌سازی دیکشنری استفاده شده است.

def invert_dictionary(input:dict)->dict:    return {v: k for k, v in dict1.items()} dict1 = {“a”: 1, “b”: 2, “c”: 3} assert invert_dictionary(dict1) == {1: “a”, 2: “b”, 3: “c”}

ذخیره چندین دیکشنری در یک فایل

به جای استفاده از pickle برای ذخیره یک شیء در یک فایل می‌توانید از shelve برای ذخیره چند شیء در فایل استفاده کنید.

import shelve dict1 = {“a”: 1, “b”: 2, “c”: 3}dict2 = {1: “a”, 2: “b”, 3: “c”}dict3 = {}dict4 = {} with shelve.open(“dictionary-shelf”, “c”) as shelf:    shelf[“first”] = dict1    shelf[“second”] = dict2 with shelve.open(“dictionary-shelf”, “r”) as shelf:    dict3 = shelf[“first”]    dict4 = shelf[“second”] assert dict1 == dict3assert dict2 == dict4assert dict1 != dict2assert dict3 != dict4

تبدیل دیکشنری به JSON

کاری آسان‌تر از این در پایتون وجود ندارد. مثال‌هایی از این مورد را در ترفندهای شماره 6 و 10 این مطلب مشاهده کردیم. به جز در مواردی که دیکشنری شما شامل کلاس‌های تعریف شده از سوی کاربر، اشیای datetime، مجموعه (set) یا دیگر اشیای پایتون باشد، می‌توانید از این روش استفاده کنید.

در این حالت یک زیرکلاس از شیء JSONEncoder به دست می‌آید که مورد خاص ما را به روش متفاوتی مدیریت می‌کند. در خط 12 از «نوع‌بندی اردکی» (duck typing) استفاده کرده‌ایم. قصد ما این است که ببینیم آیا شیء به صورت یک دنباله تکرارپذیر عمل می‌کند یا نه تا در این صورت آن را به یک لیست تبدیل کنیم. اگر شیئی یک تکرارپذیر (iterable) نداشته باشد، یک استثنا ایجاد می‌شود که در خط 16 نادیده گرفته شده است.

import jsonfrom datetime import datetime class PythonObjectEncoder(json.JSONEncoder):     def default(self, an_object_value):         if isinstance(an_object_value, str):            return an_object_value         try:            iterable = iter(an_object_value)            return list(iterable)        except TypeError:            pass  # this object is not iterable         if isinstance(an_object_value, datetime):            return an_object_value.isoformat()         elif hasattr(an_object_value, “__class__”):            return an_object_value.__dict__         return super().default(an_object_value) def dict_to_json(the_dict: dict) -> str:     return PythonObjectEncoder().encode(the_dict) class SimpleClass:    def __init__(self):        self.instance_value = 10 b = SimpleClass() dict1: dict = {}dict1[“string”] = “Hello, World!”dict1[“datetime”] = datetime(2030, 12, 31)dict1[“nothing”] = Nonedict1[“set”]: set = {0, 1, 2, 3}dict1[“tuple”] = (“apples”, “fresh”, “green”)dict1[“list”] = [“a”, “b”, “c”]dict1[“simple_class”] = SimpleClass() assert (        dict_to_json(dict1) ==            (                ‘{“string”: “Hello, World!”,’                 ‘ “datetime”: “2030-12-31T00:00:00”,’                ‘ “nothing”: null,’                ‘ “set”: [0, 1, 2, 3],’                ‘ “tuple”: [“apples”, “fresh”, “green”],’                ‘ “list”: [“a”, “b”, “c”],’                ‘ “simple_class”: {“instance_value”: 10}}’            )    )

حذف چندین آیتم از دیکشنری در طی تکرار

در پایتون 3 متد items()‎ یک تکرارکننده (iterator) بازگشت می‌دهد. بنابراین تلاش برای حذف یک آیتم منجر به ایجاد یک «خطای زمان اجرا» (RuntimeError) می‌شود. ما با یادداشت‌برداری موقت از همه آیتم‌هایی که قرار است حذف شوند، می‌توانیم از بروز این خطا جلوگیری کنیم. در مثال زیر همه آیتم‌هایی که مقدارشان عدد زوج است حذف می‌شوند.

def remove_even_items(the_dict: dict):     # collect the keys of all the items to remove    delete_these = set(k for k, v in the_dict.items() if v % 2 == 0)     for delete_this in delete_these:        del the_dict[delete_this]     return the_dict dict1: dict = dict(enumerate(range(13)))assert remove_even_items(dict1) == {1: 1, 3: 3, 5: 5, 7: 7, 9: 9, 11: 11}

سخن پایانی

امیدواریم این مطلب مورد توجه شما قرار گرفته باشد. هر گونه دیدگاه یا پیشنهاد خود را در مورد موضوع این مطلب در بخش نظرات این نوشته با ما و دیگر خوانندگان مجله فرادرس در میان بگذارید.

عناوین محتوای این مطلب پنهان سازی