FA-TOOLS — Header Component

ست (Set) در پایتون — آموزش کامل با کدهای آماده

سلام رفیق برنامه‌نویس! اگه دنبال یه راهکار توپ برای مدیریت داده‌های یونیک و انجام عملیات‌های ریاضی روی مجموعه‌ها هستی، پایتون یه جعبه ابزار خفن به اسم “ست” (Set) رو برات کنار گذاشته. ست‌ها یکی از اون ساختارهای داده‌ای هستن که شاید کمتر به چشم بیان، اما وقتی کارشون رو بلد باشی، می‌تونن خیلی از دردسرات رو آب کنن و کدهات رو تمیزتر و بهینه‌تر کنن. تو این مقاله قراره با هم غواصی کنیم تو دنیای ست‌ها، از ساختشون تا تمام عملیات‌های پیچیده‌ای که میشه روشون انجام داد. آماده‌ای کدنویسی رو به مرحله بعدی ببری؟ پس بزن بریم!

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

✨ نقشه راه آموزش ست‌ها در پایتون ✨

ست (Set) در پایتون — آموزش کامل با کدهای آماده — تصویر 1

اینجا یه نگاه سریع به چیزایی که قراره یاد بگیریم داریم. آماده‌سازی برای یه سفر هیجان‌انگیز!

موضوع اصلی نکات کلیدی
💡 ست چیه و چرا مهمه؟ عناصر یکتا، بدون ترتیب، غیرقابل تغییر (عناصر)، سریع در جستجو
🛠️ چطوری ست بسازیم؟ با آکولاد {}، تابع set()، از لیست یا تاپل
➕➖ عملیات‌های اصلی ست اجتماع، اشتراک، تفاضل، تفاضل متقارن، زیرمجموعه و…
⚙️ متدهای کاربردی ست add(), remove(), discard(), pop(), clear(), update()
🚀 کاربردهای واقعی ست حذف تکراری‌ها، تست عضویت، الگوریتم‌های گراف
⚠️ مشکلات رایج و راه‌حل‌ها خطاهای TypeError، تغییرناپذیری، عملکرد

📞 نیاز به کمک یا مشاوره داری؟ با ما تماس بگیر: 09202232789

فهرست مطالب

ست (Set) در پایتون — آموزش کامل با کدهای آماده — تصویر 2

ست (Set) چیست و چه ویژگی‌هایی دارد؟

ست (Set) در پایتون — آموزش کامل با کدهای آماده — تصویر 3

تصور کن یه عالمه عدد داری و می‌خوای بدونی کدومشون تکراری نیستن یا مثلاً عناصر مشترک بین دو گروه مختلف رو پیدا کنی. اینجا ست‌ها به کارت میان! “ست” (Set) در پایتون یه نوع مجموعه داده هست که برای ذخیره آیتم‌های منحصر به فرد (Unique) و بدون ترتیب استفاده میشه. یعنی هر آیتم فقط یک بار می‌تونه تو ست وجود داشته باشه و ترتیب قرار گرفتن آیتم‌ها هم برامون مهم نیست.

ویژگی‌های کلیدی ست‌ها:

  • عناصر منحصر به فرد (Unique Elements): این مهمترین ویژگی ست‌هاست. اگه چند بار یه آیتم رو به ست اضافه کنی، فقط یک نمونه ازش نگهداری میشه.
  • بدون ترتیب (Unordered): برخلاف لیست‌ها و تاپل‌ها، ست‌ها ترتیب مشخصی ندارن. یعنی نمی‌تونی با ایندکس به آیتم‌ها دسترسی پیدا کنی (مثل my_set[0]).
  • تغییرپذیر (Mutable): یعنی می‌تونی بعد از ساختن ست، بهش آیتم اضافه یا ازش کم کنی.
  • فقط شامل عناصر غیرقابل تغییر (Immutable Elements): خود ست تغییرپذیره، اما عناصری که داخلش قرار می‌گیرن باید غیرقابل تغییر باشن. مثلاً می‌تونی عدد، رشته، تاپل یا حتی frozenset داخل ست داشته باشی، ولی نمی‌تونی لیست یا دیکشنری رو مستقیم داخل ست بذاری. چون اینا خودشون تغییرپذیرن و پایتون نمی‌تونه به درستی هش (Hash) اون‌ها رو محاسبه کنه.
  • سریع در عملیات جستجو (Fast Lookups): ست‌ها برای بررسی وجود یک عضو (in operator) فوق‌العاده سریع عمل می‌کنن که این ویژگی تو خیلی از الگوریتم‌ها به دردت می‌خوره.

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

ساختن یه ست تو پایتون واقعاً راحته و چند تا راه مختلف داره.

۱. با استفاده از آکولاد {}

ساده‌ترین راه برای ساختن یه ست اینه که آیتم‌هات رو بین دو تا آکولاد بذاری. فقط حواست باشه که اگه ست خالی بخوای بسازی، نباید از {} استفاده کنی، چون اینجوری یه دیکشنری خالی میسازی!


# ساختن یه ست با مقادیر اولیه
my_set = {1, 2, 3, 4, 5}
print(f"Set من: {my_set}")
# خروجی: Set من: {1, 2, 3, 4, 5} (ترتیب ممکنه فرق کنه)

# امتحان کردن با مقادیر تکراری
another_set = {1, 2, 2, 3, 4, 4, 5}
print(f"Set بدون تکراری: {another_set}")
# خروجی: Set بدون تکراری: {1, 2, 3, 4, 5}

# ست با انواع داده مختلف (البته غیرقابل تغییر!)
mixed_set = {1, "hello", 3.14, (1, 2, 3)}
print(f"ست ترکیبی: {mixed_set}")
# خروجی: ست ترکیبی: {1, 'hello', 3.14, (1, 2, 3)}
    

۲. ساختن ست خالی با set()

همونطور که گفتم، برای ساختن یه ست خالی باید از تابع set() استفاده کنی:


empty_set = set()
print(f"ست خالی: {empty_set}")
# خروجی: ست خالی: set()
print(f"نوع empty_set: {type(empty_set)}")
# خروجی: نوع empty_set: 

empty_dict = {}
print(f"نوع empty_dict: {type(empty_dict)}")
# خروجی: نوع empty_dict: 
    

۳. تبدیل لیست یا تاپل به ست

یکی از کاربردهای عالی ست‌ها، حذف مقادیر تکراری از یه لیست یا تاپل هست. کافیه اون‌ها رو به تابع set() پاس بدی:


my_list = [1, 2, 2, 3, 4, 4, 5, 1]
unique_numbers = set(my_list)
print(f"لیست اصلی: {my_list}")
print(f"اعداد یونیک از لیست: {unique_numbers}")
# خروجی:
# لیست اصلی: [1, 2, 2, 3, 4, 4, 5, 1]
# اعداد یونیک از لیست: {1, 2, 3, 4, 5}

my_tuple = (10, 20, 20, 30, 40, 10)
unique_tuple_elements = set(my_tuple)
print(f"تاپل اصلی: {my_tuple}")
print(f"عناصر یونیک از تاپل: {unique_tuple_elements}")
# خروجی:
# تاپل اصلی: (10, 20, 20, 30, 40, 10)
# عناصر یونیک از تاپل: {40, 10, 20, 30}
    

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

عملیات‌های ریاضی روی ست‌ها

ست‌ها به صورت طبیعی از عملیات‌های ریاضی مجموعه‌ها مثل اجتماع، اشتراک، تفاضل و تفاضل متقارن پشتیبانی می‌کنن. این یکی از جذاب‌ترین بخش‌های کار با ست‌هاست!

۱. اجتماع (Union)

اجتماع دو ست، یه ست جدید برمی‌گردونه که شامل تمام عناصر منحصر به فرد از هر دو ست هست. می‌تونی از متد union() یا عملگر | استفاده کنی.


set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

# با استفاده از متد union()
union_set_method = set1.union(set2)
print(f"اجتماع (متد): {union_set_method}")
# خروجی: اجتماع (متد): {1, 2, 3, 4, 5, 6}

# با استفاده از عملگر |
union_set_operator = set1 | set2
print(f"اجتماع (عملگر): {union_set_operator}")
# خروجی: اجتماع (عملگر): {1, 2, 3, 4, 5, 6}
    

۲. اشتراک (Intersection)

اشتراک دو ست، یه ست جدید برمی‌گردونه که فقط شامل عناصر مشترک بین هر دو ست هست. از متد intersection() یا عملگر & استفاده کن.


set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

# با استفاده از متد intersection()
intersection_set_method = set1.intersection(set2)
print(f"اشتراک (متد): {intersection_set_method}")
# خروجی: اشتراک (متد): {3, 4}

# با استفاده از عملگر &
intersection_set_operator = set1 & set2
print(f"اشتراک (عملگر): {intersection_set_operator}")
# خروجی: اشتراک (عملگر): {3, 4}
    

۳. تفاضل (Difference)

تفاضل دو ست، یه ست جدید برمی‌گردونه که شامل عناصری هست که در ست اول وجود دارن ولی در ست دوم نه. از متد difference() یا عملگر - استفاده کن.


set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

# با استفاده از متد difference()
difference_set_method = set1.difference(set2)
print(f"تفاضل (متد): {difference_set_method}")
# خروجی: تفاضل (متد): {1, 2}

# با استفاده از عملگر -
difference_set_operator = set1 - set2
print(f"تفاضل (عملگر): {difference_set_operator}")
# خروجی: تفاضل (عملگر): {1, 2}

# تفاضل برعکس
difference_set_reverse = set2 - set1
print(f"تفاضل (برعکس): {difference_set_reverse}")
# خروجی: تفاضل (برعکس): {5, 6}
    

۴. تفاضل متقارن (Symmetric Difference)

تفاضل متقارن دو ست، یه ست جدید برمی‌گردونه که شامل عناصری هست که در یکی از ست‌ها وجود دارن، ولی در هر دو ست مشترک نیستن. از متد symmetric_difference() یا عملگر ^ استفاده کن.


set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

# با استفاده از متد symmetric_difference()
sym_diff_set_method = set1.symmetric_difference(set2)
print(f"تفاضل متقارن (متد): {sym_diff_set_method}")
# خروجی: تفاضل متقارن (متد): {1, 2, 5, 6}

# با استفاده از عملگر ^
sym_diff_set_operator = set1 ^ set2
print(f"تفاضل متقارن (عملگر): {sym_diff_set_operator}")
# خروجی: تفاضل متقارن (عملگر): {1, 2, 5, 6}
    

۵. زیرمجموعه (Subset)، ابرمجموعه (Superset) و جدا از هم (Disjoint)

این عملیات‌ها برای بررسی ارتباط بین دو ست استفاده میشن و خروجی True یا False دارن.

  • issubset(): آیا ست اول زیرمجموعه ست دوم است؟ (همه عناصر ست اول در ست دوم وجود دارند؟)
  • issuperset(): آیا ست اول ابرمجموعه ست دوم است؟ (همه عناصر ست دوم در ست اول وجود دارند؟)
  • isdisjoint(): آیا دو ست هیچ عنصر مشترکی ندارند؟ (اشتراک آن‌ها تهی است؟)

set_a = {1, 2}
set_b = {1, 2, 3, 4}
set_c = {5, 6}

print(f"آیا set_a زیرمجموعه set_b است؟ {set_a.issubset(set_b)}") # True
print(f"آیا set_b زیرمجموعه set_a است؟ {set_b.issubset(set_a)}") # False
print(f"آیا set_b ابرمجموعه set_a است؟ {set_b.issuperset(set_a)}") # True
print(f"آیا set_a و set_c جدا از هم هستند؟ {set_a.isdisjoint(set_c)}") # True
print(f"آیا set_a و set_b جدا از هم هستند؟ {set_a.isdisjoint(set_b)}") # False
    

متدهای کاربردی ست‌ها

علاوه بر عملیات‌های ریاضی، ست‌ها متدهای زیادی دارن که بهت اجازه میدن ست‌ها رو تغییر بدی یا اطلاعاتی در موردشون به دست بیاری.

۱. اضافه کردن آیتم: add()

با متد add() می‌تونی یه عنصر رو به ست اضافه کنی. اگه عنصر از قبل وجود داشته باشه، هیچ اتفاقی نمیفته.


my_numbers = {1, 2, 3}
my_numbers.add(4)
print(f"بعد از اضافه کردن 4: {my_numbers}") # {1, 2, 3, 4}
my_numbers.add(1) # اضافه نمی‌شه چون تکراریه
print(f"بعد از اضافه کردن 1 دوباره: {my_numbers}") # {1, 2, 3, 4}
    

۲. حذف کردن آیتم: remove()، discard()، pop() و clear()

برای حذف آیتم‌ها چند تا گزینه داری:

  • remove(element): عنصر مشخص شده رو حذف می‌کنه. اگه عنصر وجود نداشته باشه، خطای KeyError میده.
  • discard(element): عنصر مشخص شده رو حذف می‌کنه. اگه عنصر وجود نداشته باشه، هیچ خطایی نمیده. این متد امن‌تره.
  • pop(): یه عنصر تصادفی (Random) رو از ست حذف می‌کنه و برمی‌گردونه. چون ست‌ها بدون ترتیب هستن، نمی‌تونی پیش‌بینی کنی کدوم عنصر حذف میشه. اگه ست خالی باشه، خطای KeyError میده.
  • clear(): تمام عناصر رو از ست حذف می‌کنه و ست رو خالی می‌کنه.

my_set = {10, 20, 30, 40}

my_set.remove(20)
print(f"بعد از remove(20): {my_set}") # {10, 30, 40}

my_set.discard(30)
print(f"بعد از discard(30): {my_set}") # {10, 40}

my_set.discard(99) # این عنصر وجود نداره، ولی خطا نمیده
print(f"بعد از discard(99): {my_set}") # {10, 40}

# my_set.remove(99) # این خط خطا میده: KeyError: 99

random_element = my_set.pop()
print(f"عنصر حذف شده با pop(): {random_element}")
print(f"ست بعد از pop(): {my_set}") # مثلاً {40}

my_set.clear()
print(f"ست بعد از clear(): {my_set}") # set()
    

۳. آپدیت کردن ست: update()، intersection_update() و …

این متدها ست فعلی رو تغییر میدن و یه ست جدید برنمی‌گردونن.

  • update(other_set): عناصر ست دیگه رو به ست فعلی اضافه می‌کنه (مثل اجتماع، ولی ست فعلی رو تغییر میده).
  • intersection_update(other_set): ست فعلی رو با اشتراک خودش با ست دیگه جایگزین می‌کنه.
  • difference_update(other_set): عناصر مشترک با ست دیگه رو از ست فعلی حذف می‌کنه.
  • symmetric_difference_update(other_set): ست فعلی رو با تفاضل متقارن خودش با ست دیگه جایگزین می‌کنه.

s1 = {1, 2, 3}
s2 = {3, 4, 5}

s1.update(s2)
print(f"s1 بعد از update(s2): {s1}") # {1, 2, 3, 4, 5}

s3 = {1, 2, 3}
s4 = {3, 4, 5}
s3.intersection_update(s4)
print(f"s3 بعد از intersection_update(s4): {s3}") # {3}

s5 = {1, 2, 3}
s6 = {3, 4, 5}
s5.difference_update(s6)
print(f"s5 بعد از difference_update(s6): {s5}") # {1, 2}

s7 = {1, 2, 3}
s8 = {3, 4, 5}
s7.symmetric_difference_update(s8)
print(f"s7 بعد از symmetric_difference_update(s8): {s7}") # {1, 2, 4, 5}
    

Frozenset: یه ست غیرقابل تغییر

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

چرا frozenset؟

  • برای استفاده به عنوان عضو یک ست دیگه: همونطور که گفتیم، عناصر ست‌ها باید غیرقابل تغییر باشن. پس نمی‌تونی یه set رو عضو یه set دیگه کنی، اما می‌تونی یه frozenset رو به عنوان عضو یه set اضافه کنی.
  • برای استفاده به عنوان کلید دیکشنری: کلیدهای دیکشنری هم باید غیرقابل تغییر باشن. frozenset می‌تونه به عنوان کلید دیکشنری استفاده بشه.
  • ایمنی و قابلیت هش‌پذیری: چون frozenset تغییر نمی‌کنه، پایتون می‌تونه هش (Hash) اون رو محاسبه کنه و ازش تو ساختارهای داده‌ای مثل ست‌ها و دیکشنری‌ها (به عنوان کلید) استفاده کنه.

# ساختن frozenset
frozen_s = frozenset([1, 2, 3])
print(f"فروزن ست من: {frozen_s}")

# امتحان برای اضافه کردن آیتم (خطا میده!)
# frozen_s.add(4) # AttributeError: 'frozenset' object has no attribute 'add'

# استفاده از frozenset به عنوان عضو یک ست
nested_set = {frozenset({1, 2}), frozenset({3, 4})}
print(f"ست تو در تو: {nested_set}")

# استفاده از frozenset به عنوان کلید دیکشنری
my_dict = {frozenset({'apple', 'banana'}): "فروخته شد", frozenset({'orange'}): "موجود است"}
print(f"دیکشنری با کلید فروزن ست: {my_dict}")
    

این ویژگی‌ها رو میشه در کدهای آماده و اسنیپت‌های مختلف دید.

چه زمانی از ست‌ها استفاده کنیم؟

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

۱. حذف عناصر تکراری

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


numbers_with_duplicates = [1, 2, 3, 2, 1, 4, 5, 4]
unique_numbers = list(set(numbers_with_duplicates))
print(f"اعداد بدون تکرار: {unique_numbers}")
# خروجی: اعداد بدون تکرار: [1, 2, 3, 4, 5] (ترتیب ممکنه فرق کنه)
    

۲. تست عضویت سریع (Membership Testing)

اگه قراره مکرراً بررسی کنی که آیا یه عنصر تو یه مجموعه بزرگی از داده‌ها وجود داره یا نه، ست‌ها بهترین گزینه هستن. عملیات in برای ست‌ها خیلی سریع‌تر از لیست‌هاست، خصوصاً برای مجموعه‌های بزرگ.


my_large_set = set(range(1000000)) # یه ست بزرگ
search_element = 543210

# تست سرعت برای ست
import time
start_time = time.time()
if search_element in my_large_set:
    print("عنصر در ست پیدا شد!")
end_time = time.time()
print(f"زمان جستجو در ست: {end_time - start_time:.6f} ثانیه")

# مقایسه با لیست (برای مقادیر بزرگ تفاوت خیلی زیاد میشه)
my_large_list = list(range(1000000))
start_time = time.time()
if search_element in my_large_list:
    print("عنصر در لیست پیدا شد!")
end_time = time.time()
print(f"زمان جستجو در لیست: {end_time - start_time:.6f} ثانیه")
    

۳. عملیات‌های ریاضی مجموعه‌ها

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


# پیدا کردن دانش آموزانی که هم در کلاس A و هم در کلاس B هستند
class_a = {"علی", "رضا", "مریم", "حسین"}
class_b = {"رضا", "سارا", "مریم", "احمد"}

common_students = class_a.intersection(class_b)
print(f"دانش آموزان مشترک: {common_students}") # {'رضا', 'مریم'}

# دانش آموزانی که فقط در کلاس A هستند
only_in_a = class_a.difference(class_b)
print(f"دانش آموزان فقط در کلاس A: {only_in_a}") # {'علی', 'حسین'}
    

بررسی عملکرد و پیچیدگی زمانی (Time Complexity)

یکی از دلایل اصلی سرعت بالای ست‌ها تو عملیات جستجو، ساختار داخلی اون‌هاست. ست‌ها در پایتون با استفاده از “جدول هش” (Hash Table) پیاده‌سازی شدن. این ساختار به پایتون اجازه میده تا به سرعت تشخیص بده یه عنصر وجود داره یا نه.

پیچیدگی زمانی عملیات‌های رایج:

عملیات پیچیدگی زمانی (میانگین)
add(element) O(1)
remove(element) / discard(element) O(1)
element in my_set (تست عضویت) O(1)
len(my_set) O(1)
union() / intersection() / difference() O(len(s1) + len(s2))

**توضیح O(1):** یعنی زمان انجام عملیات ثابت است و به تعداد عناصر ست بستگی ندارد. این فوق‌العاده سریع است!
**توضیح O(len(s1) + len(s2)):** یعنی زمان انجام عملیات به مجموع تعداد عناصر دو ستی که روی آن‌ها عملیات انجام می‌شود بستگی دارد.

نکات کاربردی و اشتباهات رایج

حتی با ابزارهای قدرتمند هم ممکنه اشتباهاتی ازمون سر بزنه. اینجا چند تا نکته و اشتباه رایج رو با هم بررسی می‌کنیم:

۱. ساختن ست خالی اشتباه

همونطور که قبلاً گفتم، {} یه دیکشنری خالی میسازه، نه ست خالی. همیشه از set() برای ست خالی استفاده کن.


# اشتباه:
# empty_set_wrong = {}
# print(type(empty_set_wrong)) # 

# صحیح:
empty_set_correct = set()
print(type(empty_set_correct)) # 
    

۲. تلاش برای ذخیره عناصر تغییرپذیر

لیست‌ها و دیکشنری‌ها (یا حتی ست‌های معمولی) چون تغییرپذیر هستن، نمی‌تونن عضو یه ست باشن. پایتون بهت TypeError: unhashable type: 'list' میده. اگه واقعاً نیاز داری یه مجموعه رو به عنوان عضو ست ذخیره کنی، از frozenset استفاده کن.


# این کار خطا میده
# my_problematic_set = {[1, 2], [3, 4]} # TypeError: unhashable type: 'list'

# راه حل: استفاده از frozenset
my_valid_set = {frozenset([1, 2]), frozenset([3, 4])}
print(f"ست معتبر: {my_valid_set}")
    

۳. عدم وجود ترتیب

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


my_set = {5, 1, 3, 2, 4}
print(f"ست: {my_set}") # ترتیب نامشخص

my_list = sorted(list(my_set))
print(f"لیست مرتب شده از ست: {my_list}") # [1, 2, 3, 4, 5]
    

عیب‌یابی سریع (Troubleshooting)

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

مشکل ۱: دریافت TypeError: unhashable type: 'list'

سناریو: می‌خوای یه لیست از لیست‌ها رو به ست تبدیل کنی یا لیستی رو به عنوان عضو به ست اضافه کنی.

دلیل: عناصر ست‌ها باید “هش‌پذیر” (hashable) باشن، یعنی غیرقابل تغییر. لیست‌ها تغییرپذیرن و هش‌پذیر نیستن.

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


# ❌ مشکل:
# my_sets = {[1, 2], [3, 4]} # Error!

# ✅ راه حل با تاپل:
my_sets_with_tuples = {(1, 2), (3, 4)}
print(f"با تاپل‌ها: {my_sets_with_tuples}")

# ✅ راه حل با frozenset:
my_sets_with_frozensets = {frozenset([1, 2]), frozenset([3, 4])}
print(f"با فروزن‌ست: {my_sets_with_frozensets}")
        

مشکل ۲: KeyError هنگام حذف عنصر

سناریو: داری با remove() یه عنصر رو حذف می‌کنی که اصلاً تو ستت وجود نداره.

دلیل: متد remove() اگه عنصر مورد نظر رو پیدا نکنه، KeyError میده.

راه‌حل: از متد discard() استفاده کن که اگه عنصر وجود نداشت، خطایی نمیده. یا قبل از حذف، وجود عنصر رو با if element in my_set: بررسی کن.


my_set = {1, 2, 3}

# ❌ مشکل:
# my_set.remove(4) # KeyError: 4

# ✅ راه حل با discard():
my_set.discard(4)
print(f"بعد از discard(4): {my_set}") # {1, 2, 3} (بدون خطا)

# ✅ راه حل با بررسی قبلی:
if 4 in my_set:
    my_set.remove(4)
else:
    print("4 در ست نیست، حذف نمی‌شود.")
        

مشکل ۳: ست‌ها ترتیب عناصر را حفظ نمی‌کنند

سناریو: انتظار داری ست، عناصری رو که اضافه کردی، به همون ترتیب نشون بده.

دلیل: ست‌ها ذاتاً بدون ترتیب (unordered) هستن. این بخشی از طراحی اون‌ها برای بهینه‌سازی سرعت عملیات جستجو هست.

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


my_data = {50, 20, 10, 40, 30}
print(f"ست من: {my_data}") # خروجی ممکنه {40, 10, 50, 20, 30} باشه

ordered_data = sorted(list(my_data))
print(f"داده‌های مرتب شده: {ordered_data}") # [10, 20, 30, 40, 50]
        

مشکل ۴: تفاوت بین union() و update()

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

دلیل: تفاوت اصلی اینه که union() یه ست کاملاً جدید برمی‌گردونه و ست‌های اصلی رو دست نمی‌زنه، در حالی که update() ست فراخوانی کننده رو به صورت درجا (in-place) تغییر میده.

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


set_a = {1, 2}
set_b = {3, 4}

new_set = set_a.union(set_b)
print(f"ست جدید با union(): {new_set}") # {1, 2, 3, 4}
print(f"set_a اصلی بعد از union(): {set_a}") # {1, 2} (تغییر نکرده)

set_c = {1, 2}
set_d = {3, 4}
set_c.update(set_d)
print(f"set_c بعد از update(set_d): {set_c}") # {1, 2, 3, 4} (تغییر کرده)
print(f"set_d اصلی بعد از update(): {set_d}") # {3, 4} (تغییر نکرده)
        

سوالات متداول (FAQ)

آیا ترتیب عناصر در ست‌های پایتون مهم است؟

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

چگونه یک ست خالی در پایتون ایجاد کنیم؟

برای ایجاد یک ست خالی، باید از تابع set() استفاده کنید: my_empty_set = set(). استفاده از {} یک دیکشنری خالی ایجاد می‌کند، نه یک ست خالی.

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

خیر، عناصر ست‌ها باید “هش‌پذیر” (hashable) باشند، به این معنی که باید غیرقابل تغییر (immutable) باشند. لیست‌ها و دیکشنری‌ها قابل تغییر (mutable) هستند و بنابراین نمی‌توانند عضو یک ست باشند. برای این منظور می‌توانید از تاپل‌ها یا frozenset (یک نسخه غیرقابل تغییر از ست) استفاده کنید.

تفاوت remove() و discard() چیست؟

هر دو متد برای حذف یک عنصر از ست استفاده می‌شوند. تفاوت اصلی در این است که اگر عنصر مورد نظر در ست وجود نداشته باشد، remove() خطای KeyError ایجاد می‌کند، در حالی که discard() هیچ خطایی نمی‌دهد. discard() برای حذف امن‌تر است.

function copyCode(button) {
const codeBlock = button.previousElementSibling.querySelector(‘code’);
const textToCopy = codeBlock.innerText;

navigator.clipboard.writeText(textToCopy).then(() => {
const originalText = button.innerText;
button.innerText = ‘کپی شد!’;
setTimeout(() => {
button.innerText = originalText;
}, 2000);
}).catch(err => {
console.error(‘Failed to copy text: ‘, err);
alert(‘خطا در کپی کردن کد.’);
});
}

/* Basic responsive styles for the article content.
These styles are designed to be generic and work well in a block editor. */
body {
font-family: ‘Segoe UI’, Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
margin: 0;
padding: 20px;
background-color: #fdfdfd;
}

/* Simulate H1 for robust copy-paste */
h1 {
font-size: 2.5em;
font-weight: bold;
color: #333;
margin-top: 0;
margin-bottom: 20px;
}

/* Simulate H2 for robust copy-paste */
h2 {
font-size: 2em;
font-weight: bold;
color: #333;
margin-top: 40px;
margin-bottom: 15px;
border-bottom: 2px solid #eee;
padding-bottom: 5px;
}

/* Simulate H3 for robust copy-paste */
h3 {
font-size: 1.5em;
font-weight: bold;
color: #555;
margin-top: 30px;
margin-bottom: 10px;
}

p {
margin-bottom: 1em;
font-size: 1.05em;
}

ul {
margin-bottom: 1em;
padding-left: 20px;
}

li {
margin-bottom: 0.5em;
font-size: 1.05em;
}

a {
color: #007bff;
text-decoration: none;
}

a:hover {
text-decoration: underline;
}

code {
background-color: #f0f0f0;
padding: 2px 4px;
border-radius: 3px;
font-family: ‘Courier New’, Courier, monospace;
font-size: 0.9em;
}

pre {
background-color: #f8f8f8;
border: 1px solid #ddd;
padding: 15px;
border-radius: 5px;
overflow-x: auto; /* Essential for responsiveness of code blocks */
}

pre code {
background-color: transparent;
padding: 0;
border: none;
display: block;
white-space: pre; /* Ensure proper pre-formatted text handling */
font-size: 0.9em; /* Adjust font size for better mobile viewing */
}

table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
margin-bottom: 20px;
display: block; /* Make table responsive by default */
overflow-x: auto; /* Allow horizontal scrolling on small screens */
}

th, td {
padding: 12px 15px;
border: 1px solid #ddd;
text-align: left;
white-space: nowrap; /* Prevent text wrapping in table cells */
}

thead tr {
background-color: #007bff;
color: white;
}

tbody tr:nth-child(even) {
background-color: #f2f2f2;
}

tbody tr:hover {
background-color: #e0e0e0;
}

/* Specific styles for infographic box */
.infographic-box {
background-color: #e0f7fa;
border-left: 5px solid #00bcd4;
padding: 20px;
margin-bottom: 30px;
border-radius: 8px;
}

.infographic-box h2 {
color: #00796b;
margin-top: 0;
border-bottom: none;
padding-bottom: 0;
}

.infographic-box table {
margin-top: 15px;
border-collapse: collapse;
}

.infographic-box th, .infographic-box td {
border: 1px solid #00bcd4;
padding: 10px;
}

.infographic-box th {
background-color: #b2ebf2;
color: #004d40;
}

.infographic-box tr:nth-child(odd) td {
background-color: #f0f8ff;
}

.infographic-box p {
color: #444;
}

/* Troubleshooting Box Styles */
.troubleshooting-box {
background-color: #fff3e0;
border-left: 5px solid #ff9800;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.troubleshooting-box p {
color: #333;
margin-top: 0;
}
.troubleshooting-box code {
background-color: #f8f8f8;
border: 1px solid #ddd;
}

/* FAQ Box Styles */
div[itemtype=”https://schema.org/Question”] h3 {
color: #0056b3;
font-size: 1.5em; /* Ensure consistent heading size */
margin-top: 20px; /* Space out questions */
margin-bottom: 10px;
}
div[itemtype=”https://schema.org/Answer”] {
background-color: #f0f8ff;
border-left: 3px solid #007bff;
padding: 15px;
border-radius: 4px;
margin-top: 10px;
margin-bottom: 15px; /* Space out answers */
}
div[itemtype=”https://schema.org/Answer”] p {
color: #333;
margin: 0;
}

/* Copy Code Button */
button {
background-color: #007bff;
color: white;
padding: 8px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
margin-top: 10px;
display: inline-block; /* Ensure it doesn’t break layout */
}
button:hover {
background-color: #0056b3;
}

/* Responsive adjustments */
@media (max-width: 768px) {
h1 {
font-size: 2em;
}
h2 {
font-size: 1.6em;
}
h3 {
font-size: 1.3em;
}
body {
padding: 15px;
}
table, pre {
word-wrap: break-word; /* Allow long words to break */
overflow-x: auto; /* Ensure horizontal scroll for tables/code */
}
th, td {
font-size: 0.9em;
padding: 8px 10px;
white-space: nowrap; /* Prevent text wrapping in table cells */
}
.infographic-box table th, .infographic-box table td {
white-space: normal; /* Override for infographic table on small screens */
}
/* Make table header sticky for better UX on scroll */
table thead {
display: block;
position: sticky;
top: 0;
background-color: #007bff;
}
table tbody {
display: block;
overflow-y: auto;
max-height: 400px; /* Adjust as needed */
}
}
@media (max-width: 480px) {
h1 {
font-size: 1.8em;
}
h2 {
font-size: 1.4em;
}
h3 {
font-size: 1.2em;
}
body {
padding: 10px;
}
p, li {
font-size: 0.95em;
}
th, td {
padding: 6px 8px;
font-size: 0.85em;
}
}

Table of Contents

آخرین نوشته‌ها