Set (Küme) İşlemleri
Set, matematikteki küme kavramının Python'daki karşılığı. İki temel özelliği var: her eleman benzersiz (duplicate yok) ve sırasız (insertion order garanti değil). Bu iki özellik onu bazı problemlerde liste ve dictionary'den çok daha uygun yapar.
Bir parmak izi veritabanı düşün: Her parmak izi benzersiz, iki kişide aynı iz olamaz. Ve parmak izlerinin sırası önemli değil — önemli olan "bu iz veritabanında var mı?" sorusuna anında cevap vermek. İşte set tam olarak bu: benzersiz elemanlar topluluğu, O(1) üyelik testi (arama) ile. Listede arama O(n) iken set'te O(1) — bu fark milyonlarca elemanda devasa bir performans farkı yaratır.
Set Oluşturma
# Süslü parantezle
meyveler = {"elma", "armut", "muz", "çilek"}
print(meyveler) # Sıra değişebilir!
# Duplicate'lar otomatik temizlenir
sayilar = {1, 2, 3, 2, 1, 4, 3, 5}
print(sayilar) # {1, 2, 3, 4, 5}
# set() constructor ile
harfler = set("mississippi")
print(harfler) # {'m', 'i', 's', 'p'}
# Listeden set
liste = [1, 2, 3, 2, 1]
kume = set(liste)
print(kume) # {1, 2, 3}
# Range'den set
s = set(range(5))
print(s) # {0, 1, 2, 3, 4}⚠️ Boş Set Tuzağı
Bu Python'ın en bilinen gotcha'larından biri:
# ❌ Bu boş set DEĞİL — boş dictionary!
bos = {}
print(type(bos)) # <class 'dict'>
# ✅ Boş set oluşturmanın TEK yolu
bos_set = set()
print(type(bos_set)) # <class 'set'>{} boş dict oluşturur, boş set değil! Boş set için her zaman set() kullan. Bu tasarım kararı tarihsel — dict Python'a set'ten önce eklendi ve {} söz dizimini aldı.
Set'e Neler Girebilir?
Set elemanları hashable olmalıdır (dict key'leri gibi):
# ✅ Hashable tipler — set'e girebilir
s = {42, 3.14, "merhaba", (1, 2), True, None, frozenset({1, 2})}
# ❌ Mutable tipler — set'e giremez
# s = {[1, 2]} # TypeError: unhashable type: 'list'
# s = {{"a": 1}} # TypeError: unhashable type: 'dict'
# s = {{1, 2}} # TypeError: unhashable type: 'set'💡 İpucu: "Hashable" = "değiştirilemez (immutable)" olarak düşünebilirsin. int, str, float, tuple, frozenset hashable; list, dict, set hashable değil. Bu kural hem set elemanları hem dict key'leri için geçerli.
Set Operasyonları: Küme Matematiği
Set'in gerçek gücü matematiksel küme operasyonlarında. Her operasyonun hem operatör hem metod versiyonu var:
Union (Birleşim): | veya union()
İki kümenin tüm elemanlarını birleştirir (duplicate olmadan):
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# İki yol — aynı sonuç
print(a | b) # {1, 2, 3, 4, 5, 6}
print(a.union(b)) # {1, 2, 3, 4, 5, 6}
# Birden fazla set birleştirme
c = {7, 8}
print(a | b | c) # {1, 2, 3, 4, 5, 6, 7, 8}
print(a.union(b, c)) # Aynı sonuçIntersection (Kesişim): & veya intersection()
İki kümede de bulunan ortak elemanlar:
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a & b) # {3, 4}
print(a.intersection(b)) # {3, 4}Difference (Fark): - veya difference()
Birinci kümede olup ikincide olmayan elemanlar:
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a - b) # {1, 2} — a'da olup b'de olmayan
print(b - a) # {5, 6} — b'de olup a'da olmayan
print(a.difference(b)) # {1, 2}Symmetric Difference (Simetrik Fark): ^ veya symmetric_difference()
Sadece birinde olan elemanlar (ortak olmayanlar):
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a ^ b) # {1, 2, 5, 6}
print(a.symmetric_difference(b)) # {1, 2, 5, 6}
# Simetrik fark = Birleşim - Kesişim
print((a | b) - (a & b)) # {1, 2, 5, 6} — aynı sonuçVenn Diyagramı ile Görselleştirme
a = {1, 2, 3, 4} b = {3, 4, 5, 6}
┌───────────┐ ┌───────────┐
│ 1, 2 │ │ 5, 6 │
│ ┌─────┼─┼───┐ │
│ │ 3,4 │ │ │ │
│ └─────┼─┼───┘ │
└───────────┘ └───────────┘
a | b = {1, 2, 3, 4, 5, 6} (Tümü)
a & b = {3, 4} (Ortak)
a - b = {1, 2} (Sadece a)
b - a = {5, 6} (Sadece b)
a ^ b = {1, 2, 5, 6} (Ortaklar hariç)Alt Küme ve Üst Küme Kontrolü
a = {1, 2, 3}
b = {1, 2, 3, 4, 5}
# a, b'nin alt kümesi mi?
print(a <= b) # True
print(a.issubset(b)) # True
# b, a'nın üst kümesi mi?
print(b >= a) # True
print(b.issuperset(a)) # True
# Gerçek alt küme (proper subset) — eşit olamaz
print(a < b) # True — a, b'nin gerçek alt kümesi
print(a < a) # False — kendisinin gerçek alt kümesi değil
print(a <= a) # True — kendisinin alt kümesi (eşit dahil)
# Ortak eleman var mı kontrolü
x = {1, 2}
y = {3, 4}
print(x.isdisjoint(y)) # True — ortak eleman yokSet Metodları
Eleman Ekleme ve Silme
s = {1, 2, 3}
# add: Tek eleman ekle
s.add(4)
print(s) # {1, 2, 3, 4}
s.add(2) # Zaten var — hiçbir şey olmaz
print(s) # {1, 2, 3, 4}
# update: Birden fazla eleman ekle (iterable)
s.update([5, 6, 7])
print(s) # {1, 2, 3, 4, 5, 6, 7}
s.update({8, 9}, [10]) # Birden fazla iterable
print(s) # {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}Eleman Silme — 3 Farklı Yol
s = {1, 2, 3, 4, 5}
# remove: Sil — yoksa KeyError!
s.remove(3)
print(s) # {1, 2, 4, 5}
# s.remove(99) # KeyError: 99
# discard: Sil — yoksa hiçbir şey olmaz (sessiz)
s.discard(99) # Hata yok!
s.discard(4)
print(s) # {1, 2, 5}
# pop: Rastgele bir eleman sil ve döndür
silinen = s.pop()
print(f"Silinen: {silinen}")
print(s)
# clear: Tümünü sil
s.clear()
print(s) # set()remove vs discard karşılaştırması:
remove() | discard() | |
|---|---|---|
| Eleman varsa | Siler | Siler |
| Eleman yoksa | KeyError! | Sessizce geçer |
| Kullanım | Eleman olmalı diye düşünüyorsan | Olup olmadığını bilmiyorsan |
Yerinde (In-Place) Operasyonlar
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# |= : Union yerinde
a_kopya = a.copy()
a_kopya |= b
print(a_kopya) # {1, 2, 3, 4, 5, 6}
# &= : Intersection yerinde
a_kopya = a.copy()
a_kopya &= b
print(a_kopya) # {3, 4}
# -= : Difference yerinde
a_kopya = a.copy()
a_kopya -= b
print(a_kopya) # {1, 2}
# ^= : Symmetric difference yerinde
a_kopya = a.copy()
a_kopya ^= b
print(a_kopya) # {1, 2, 5, 6}frozenset: Değişmez Set
frozenset, set'in immutable versiyonu. Tıpkı tuple'ın list'in immutable versiyonu olması gibi.
# Oluşturma
fs = frozenset([1, 2, 3, 4, 5])
print(fs) # frozenset({1, 2, 3, 4, 5})
# Okuma operasyonları çalışır
print(3 in fs) # True
print(len(fs)) # 5
print(fs & {3, 4, 5, 6}) # frozenset({3, 4, 5})
# Değiştirme operasyonları ÇALIŞMAZ
# fs.add(6) # AttributeError
# fs.remove(1) # AttributeError
# fs.pop() # AttributeErrorfrozenset Neden Var?
# 1. Set içinde set — normal set hashable olmadığı için giremez
# ❌
# s = {{1, 2}, {3, 4}} # TypeError: unhashable type: 'set'
# ✅ frozenset hashable!
s = {frozenset({1, 2}), frozenset({3, 4})}
print(s)
# 2. Dict key olarak
izinler = {
frozenset({"read", "write"}): "editor",
frozenset({"read"}): "viewer",
frozenset({"read", "write", "admin"}): "admin",
}
kullanici_izin = frozenset({"read", "write"})
print(izinler[kullanici_izin]) # editor
# 3. Sabit set (değiştirilmemesi gereken)
DESTEKLENEN_DILLER = frozenset({"python", "java", "go", "rust"})Pratik Kullanımlar
1. Duplicate Temizleme
En yaygın set kullanımı — listeden tekrar eden elemanları çıkarmak:
# Basit duplicate temizleme
liste = [1, 2, 3, 2, 1, 4, 3, 5, 4, 5]
benzersiz = list(set(liste))
print(benzersiz) # [1, 2, 3, 4, 5] — sıra korunmayabilir!
# Sırayı koruyarak duplicate temizleme (Python 3.7+)
def sirali_benzersiz(iterable):
gorulenler = set()
sonuc = []
for eleman in iterable:
if eleman not in gorulenler:
gorulenler.add(eleman)
sonuc.append(eleman)
return sonuc
liste = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]
print(sirali_benzersiz(liste)) # [3, 1, 4, 5, 9, 2, 6]
# Python 3.7+ dict.fromkeys ile (daha kısa)
benzersiz = list(dict.fromkeys(liste))
print(benzersiz) # [3, 1, 4, 5, 9, 2, 6]2. Üyelik Testi (Membership Test)
# Büyük veri setinde arama
gecerli_kullanicilar = {"ahmet", "ayse", "mehmet", "fatma", "ali"}
girdi = input("Kullanıcı adı: ").lower()
if girdi in gecerli_kullanicilar: # O(1) — anında!
print("Geçerli kullanıcı")
else:
print("Kullanıcı bulunamadı")3. Ortak Elemanları Bulma
# İki kullanıcının ortak ilgi alanları
ahmet = {"python", "javascript", "müzik", "futbol", "film"}
ayse = {"java", "python", "resim", "müzik", "yüzme"}
ortak = ahmet & ayse
print(f"Ortak ilgi alanları: {ortak}") # {'python', 'müzik'}
sadece_ahmet = ahmet - ayse
print(f"Sadece Ahmet: {sadece_ahmet}")
tum_ilgiler = ahmet | ayse
print(f"Toplam benzersiz ilgi alanı: {len(tum_ilgiler)}")4. Veri Doğrulama
zorunlu_alanlar = {"isim", "email", "sifre"}
opsiyonel_alanlar = {"telefon", "adres", "dogum_tarihi"}
tum_gecerli_alanlar = zorunlu_alanlar | opsiyonel_alanlar
def form_dogrula(veri):
gelen_alanlar = set(veri.keys())
# Eksik zorunlu alanlar
eksik = zorunlu_alanlar - gelen_alanlar
if eksik:
return f"Eksik alanlar: {eksik}"
# Bilinmeyen alanlar
bilinmeyen = gelen_alanlar - tum_gecerli_alanlar
if bilinmeyen:
return f"Geçersiz alanlar: {bilinmeyen}"
return "Form geçerli ✅"
# Test
print(form_dogrula({"isim": "Ahmet", "email": "a@b.com", "sifre": "123"}))
print(form_dogrula({"isim": "Ahmet"}))
print(form_dogrula({"isim": "A", "email": "a@b", "sifre": "1", "xyz": "?"}))5. Dosya Karşılaştırma
# İki dizindeki dosya farklarını bul
dizin1_dosyalar = {"a.py", "b.py", "c.py", "d.py"}
dizin2_dosyalar = {"b.py", "c.py", "e.py", "f.py"}
sadece_dizin1 = dizin1_dosyalar - dizin2_dosyalar
sadece_dizin2 = dizin2_dosyalar - dizin1_dosyalar
ortak = dizin1_dosyalar & dizin2_dosyalar
print(f"Sadece dizin1: {sadece_dizin1}") # {'a.py', 'd.py'}
print(f"Sadece dizin2: {sadece_dizin2}") # {'e.py', 'f.py'}
print(f"Her ikisinde: {ortak}") # {'b.py', 'c.py'}Set vs List Performans: O(1) vs O(n)
Bu performans farkını somut rakamlarla görelim:
import time
# 10 milyon elemanlı veri yapıları
n = 10_000_000
buyuk_liste = list(range(n))
buyuk_set = set(range(n))
# Arama: Son elemanı bul
hedef = n - 1
# Liste araması — O(n)
baslangic = time.time()
hedef in buyuk_liste
liste_sure = time.time() - baslangic
# Set araması — O(1)
baslangic = time.time()
hedef in buyuk_set
set_sure = time.time() - baslangic
print(f"Liste araması: {liste_sure:.4f}s") # ~0.05-0.1s
print(f"Set araması: {set_sure:.6f}s") # ~0.000001s
print(f"Set {liste_sure/set_sure:.0f}x daha hızlı!")Zaman Karmaşıklığı Tablosu
| İşlem | List | Set |
|---|---|---|
x in s (arama) | O(n) | O(1) |
| Eleman ekleme | O(1)* | O(1) |
| Eleman silme (değere göre) | O(n) | O(1) |
| İterasyon | O(n) | O(n) |
\* Liste sonuna append O(1), başına insert(0, x) O(n)
Ne Zaman Set, Ne Zaman Liste?
# ✅ Set kullan: Sık arama yapıyorsan
yasakli_kelimeler = {"spam", "reklam", "dolandırıcılık"}
if kelime in yasakli_kelimeler: # O(1)
filtrele()
# ✅ Liste kullan: Sıra önemliyse
gorevler = ["kahvaltı", "iş", "spor"] # Sıralı olmalı
# ✅ Set kullan: Benzersizlik garantisi lazımsa
ziyaret_edilen_url = set()
ziyaret_edilen_url.add(url) # Otomatik dedup
# ✅ Liste kullan: Duplicate'lara izin veriliyorsa
puanlar = [100, 85, 100, 72, 85] # Aynı puan tekrar edebilir⚠️ Dikkat: Set'in hız avantajı bellek maliyetiyle gelir. Set, hash tablosu kullandığı için listeden daha fazla bellek harcar. Küçük koleksiyonlarda (< 100 eleman) fark önemsiz. Büyük koleksiyonlarda ve sık arama yapılan yerlerde set tercih et.
Yaygın Hatalar ve Anti-Pattern'ler
1. Boş Set Oluşturma
# ❌ En yaygın hata!
bos = {} # Bu dict, set değil!
print(type(bos)) # <class 'dict'>
# ✅ Doğru
bos = set()
print(type(bos)) # <class 'set'>2. Unhashable Tip Ekleme
# ❌ Liste set'e eklenemez
s = set()
# s.add([1, 2]) # TypeError: unhashable type: 'list'
# ✅ Tuple'a çevir
s.add((1, 2)) # ✅ Tuple hashable
# ❌ Dict set'e eklenemez
# s.add({"a": 1}) # TypeError: unhashable type: 'dict'
# ✅ frozenset veya tuple kullan
s.add(frozenset({"a": 1}.items())) # Çalışır ama pratik değil3. Set'te Sıra Beklemek
# ❌ Set sırasız — her çalıştırmada farklı sıra olabilir!
s = {3, 1, 4, 1, 5, 9}
for eleman in s:
print(eleman, end=" ")
# Çıktı: 1 3 4 5 9 (veya başka sırada!)
# ✅ Sıralı istiyorsan sorted() kullan
for eleman in sorted(s):
print(eleman, end=" ") # 1 3 4 5 94. Döngü İçinde Set Değiştirme
s = {1, 2, 3, 4, 5}
# ❌ RuntimeError: Set changed size during iteration
# for item in s:
# if item % 2 == 0:
# s.remove(item)
# ✅ Kopyası üzerinde dön
for item in s.copy():
if item % 2 == 0:
s.remove(item)
print(s) # {1, 3, 5}
# ✅ Veya set comprehension ile yeni set
s = {1, 2, 3, 4, 5}
s = {item for item in s if item % 2 != 0}
print(s) # {1, 3, 5}5. Set ile Aritmetik Karıştırma
# Dikkat: - operatörü set'te fark, sayılarda çıkarma
a = {1, 2, 3}
b = {2, 3, 4}
sonuc = a - b
print(sonuc) # {1} — küme farkı, çıkarma DEĞİL!
# & set'te kesişim, sayılarda bitwise AND
sonuc = a & b
print(sonuc) # {2, 3} — kesişimSet Comprehension
Liste ve dict comprehension gibi, set'ler için de tek satırda oluşturma:
# Temel set comprehension
kareler = {x**2 for x in range(10)}
print(kareler) # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
# Koşullu
cift_kareler = {x**2 for x in range(10) if x % 2 == 0}
print(cift_kareler) # {0, 4, 16, 36, 64}
# String'den benzersiz kelimeler
metin = "python güzel python harika python en iyi dil"
benzersiz_kelimeler = {kelime.lower() for kelime in metin.split()}
print(benzersiz_kelimeler)Gerçek Dünya Senaryoları
Tag/Etiket Sistemi
makale_taglari = {
"makale_1": {"python", "programlama", "tutorial"},
"makale_2": {"python", "veri-bilimi", "pandas"},
"makale_3": {"javascript", "web", "react"},
"makale_4": {"python", "web", "django"},
}
# Python ile ilgili makaleler
python_makaleleri = [
makale for makale, taglar in makale_taglari.items()
if "python" in taglar
]
print(f"Python makaleleri: {python_makaleleri}")
# Tüm benzersiz tag'ler
tum_taglar = set()
for taglar in makale_taglari.values():
tum_taglar |= taglar
print(f"Toplam {len(tum_taglar)} benzersiz tag")
# En az 2 makalede geçen tag'ler
from collections import Counter
tag_sayilari = Counter(
tag for taglar in makale_taglari.values() for tag in taglar
)
populer = {tag for tag, sayi in tag_sayilari.items() if sayi >= 2}
print(f"Popüler tag'ler: {populer}")Anagram Kontrolü
def anagram_mi(kelime1, kelime2):
"""İki kelimenin anagram olup olmadığını kontrol et."""
# Boşlukları kaldır, küçük harfe çevir
k1 = kelime1.replace(" ", "").lower()
k2 = kelime2.replace(" ", "").lower()
# Harf setleri aynı mı? (Gerekli ama yeterli değil)
if set(k1) != set(k2):
return False
# Harf sayıları da eşit mi?
from collections import Counter
return Counter(k1) == Counter(k2)
print(anagram_mi("listen", "silent")) # True
print(anagram_mi("hello", "world")) # False
print(anagram_mi("Astronomer", "Moon starer")) # TrueGrafik İlişki Takibi
# Arkadaşlık ilişkileri (çift yönlü)
arkadasliklar = {
"Ahmet": {"Ayşe", "Mehmet", "Ali"},
"Ayşe": {"Ahmet", "Fatma", "Ali"},
"Mehmet": {"Ahmet", "Fatma"},
"Ali": {"Ahmet", "Ayşe"},
"Fatma": {"Ayşe", "Mehmet"},
}
# Ahmet ve Ayşe'nin ortak arkadaşları
ortak = arkadasliklar["Ahmet"] & arkadasliklar["Ayşe"]
print(f"Ortak arkadaşlar: {ortak}") # {'Ali'}
# Ahmet'in tanımadığı kişiler
herkes = set(arkadasliklar.keys())
ahmet_bildiği = arkadasliklar["Ahmet"] | {"Ahmet"}
tanimadigi = herkes - ahmet_bildiği
print(f"Ahmet tanımıyor: {tanimadigi}") # {'Fatma'}Yetki Kontrolü
# Rol tabanlı erişim kontrolü
ROLLER = {
"admin": {"read", "write", "delete", "manage_users"},
"editor": {"read", "write"},
"viewer": {"read"},
}
def erisim_kontrol(kullanici_rolu, gereken_izin):
kullanici_izinleri = ROLLER.get(kullanici_rolu, set())
return gereken_izin in kullanici_izinleri
def toplu_erisim_kontrol(kullanici_rolu, gereken_izinler):
kullanici_izinleri = ROLLER.get(kullanici_rolu, set())
return gereken_izinler.issubset(kullanici_izinleri)
# Test
print(erisim_kontrol("editor", "write")) # True
print(erisim_kontrol("viewer", "delete")) # False
print(toplu_erisim_kontrol("admin", {"read", "delete"})) # True
print(toplu_erisim_kontrol("editor", {"read", "delete"})) # FalseÖzet
Set benzersiz elemanlar koleksiyonudur — duplicate otomatik temizlenir, sıra garanti değildir. Boş set
set()ile oluşturulur,{}dict yapar!Küme operasyonları:
|birleşim,&kesişim,-fark,^simetrik fark. Hem operatör hem metod versiyonu var.`remove()` vs `discard()`: remove olmayan elemanı silmeye çalışırsa KeyError verir, discard sessizce geçer.
frozenset set'in immutable versiyonu — dict key ve set elemanı olabilir, normal set olamaz.
Performans: Set'te arama O(1), listede O(n). Sık üyelik testi yapılan yerlerde set kullan — fark devasa.
Pratik kullanım: Duplicate temizleme, üyelik testi, veri doğrulama, dosya/koleksiyon karşılaştırma ve yetki kontrolü en yaygın senaryolar.
AI Asistan
Sorularını yanıtlamaya hazır